Imagine a small calculator GUI, with basic operations (+,-,/,*
), and in the menu we can check for example scientific calculator and a small new view with the extra functions appears beside.
I was thinking that the decorator pattern is the solution but after reading some documentation on it, I am confused now. Which pattern would be more suitable for doing such things?
1
I just took a look at the Windows XP calculator. While it’s true that the number keys and the memory keys appear in the same general location in the standard and scientific view, I believe it is to create a consistent interface for the user.
Basically, a standard / scientific calculator presents two different views to the user. The scientific view is a super set of the standard view.
One way to write a calculator application is to write the code for the scientific view. A Strategy or Command pattern would prove useful in writing your calculator code.
You can then use the same code for the standard view, as the standard view is a subset of the scientific view.
Your application would switch views depending on the option the user selected.
You should really start writing the program/app before applying patterns. See what emerges instead of forcing some arbitrary pattern. Since it is a small calculator app you want to make, then there is really no need to apply a pattern just yet.
This is usually how I work; program something, then refactor towards a pattern if there is any need to. It is quite easy otherwise to over-engineer something.
In your case, you tried to apply the decorator pattern to handling views. In terms of data it might make sense, however views are completely different. Instead start to write one basic view to do the basic operations. Then try to create the scientific view, and refactor the code so that you can reuse the basic view’s actions. You might end up with a M-V-C like structure.
7
Using MVC in conjunction with something like Prism would be a good choice in a scenario like this.
I’m not a big fan of using patterns, as it feels very restrictive if implemented from the start of a project , but it does create some sense of stability and promotes code re-use in a business if it’s company policy.
I think you don’t need a pattern in this case, but a principle. In this case, the Liskov Substitution Principle. Your small Views should implement the same Interface, so that the large View can manage them (to the extent that is needed based on the language you are using). The data Classes should also use this principle, so that the small View can be passed in data and return it to your wiring code without special consideration for what, specifically, is going on.
I find that I haven’t been able to make an application of any complexity where Liskov Substitution is perfect, and that is possibly due to limitations in me vs. the principle. But I tend to think of it like a soda machine in a restaurant. You care about the specific type in the back room where you hook up the tubes to the boxes of syrup, and you care again when it’s in your cup, but in between it all goes through the tube the same.
So I usually will have my endpoint Views type-check the IDataObject to make sure it’s congruent with the View. The other end (the back room) for me is typically a Builder and/or an Abstract Factory that has references to many specific factories and calls on the correct ones based on some condition inherent in the data (I typically have a tag in the XML data source that says “pull the factory registered under this name” and a hash that contains the Factories).
I am fortunate to develop in Flash, and I allow Flash itself to be the Factory for my Views and simply pick up references to them once they’ve been instantiated, but if you have to manually construct Views, you can probably use something similar to what I’ve described for data construction.
I applaud that you’re thinking through the design on the front in, because in real life few bosses will allow you to go back and rip out your initial experiments in favor of a more robust/maintainable design. Note that it is enough in the short-term to develop your Views and Model to Interfaces–you should find it much easier to add some kind of Factory later than it is to redo the logic that your management can physically see.
4