Join the Campaign to Stamp Out Ugly!
Gentle Readers: When you click the Play button in this post, the UI that appears isn’t very pretty. That’s because I have no graphic design skills. By changing the requests in the Client class, you could easily make a much nicer UI. Why not give it a shot and send us your revised Client request set? You can even add new Concrete Creators and Products. Send in your refinements to our comment section. Either that or click Play and see Ugly!
The Concreteness of Abstraction
The first time I went to London, I picked up a Tube Map (Map of the London Underground) and was able to get where I wanted to go. The map of London’s tube is a masterpiece of clarity and abstraction. Based on electrical circuitry, it’s very easy to find one’s way around London even on a first visit. Likewise, Paris’ Metro has an almost identical type of map for it’s underground system, and it too is easy to find where you want to go. The secret is having just enough detail to use the system and not so much detail to make its use confusing. Further the coding is clear: different colors depict different named lines. Bakerloo is brown, Circle is yellow, Central is red and District is green. At a glance you see that arriving at Heathrow Airport, you take the Piccadilly line into town (purple) and switch lines wherever you see a white circle off the Piccadilly line. The details are not provided, and the Thames river does not run along the neat geometrical angles shown on the Tube Map. It’s just a reference point and lets you know whether you’re north or south of the Thames. The river’s or tube’s exact shape doesn’t matter; the whole thing is an abstraction of London’s subway system and a major feature of the city. The details would just get in the way of clarity.
Abstraction in OOP and Design Patterns works the same way. An object only exposes as much information as the client (requesting object) requires. The perfect abstract structure in a design pattern is an Interface because it is nothing but abstract methods. The only way to really appreciate abstraction is to see it in action; so this post concentrates on demonstrating abstractions in a fundamental design pattern—the Factory Method.
Two Interfaces and some Concrete Classes
The Factory Method requires a factory interface called Creator and a “product” interface called Product. The Creator interface provides a factory method function to create concrete instances of products through the abstract Product interface. In this implementation of the Factory Method Design Pattern, both abstract participants are interfaces (Creator and Product). Figure 1 shows the relationship between the participants in the design pattern:
In a step-through of the pattern you see the following:
- Client wants a certain product. Makes request through the Creator (factory)
- Concrete creator specifies the concrete product and instantiates an instance, returning it to the Client
It’s a very straightforward pattern, but often beginners will puzzle over why all the work simply to get a class instance? The answer to that question lies more in the larger implementations and re-use of the pattern than it does in the small example used here. However, a good general answer is that it loosely binds the product to the request. If you change the product’s contents, you should not have to change anything else in the pattern. The Client makes the request through an abstraction and really doesn’t care about the details of the product. If the product is changed, the exact same request brings up a different object. However, nothing has to be changed to access the new object. Use the buttons below to download and play the example:
Chapter 2 in our book, and other posts on this blog go into detail about the Factory Method. Here the focus is on abstraction, and the Factory Method is merely used to illustrate the power of abstraction. In order to show the range of products that can be generated from the same abstract interfaces, I used both component UIs and graphic background Shape objects as products.
Using Abstractions and Programming to the Interface
One of the key principles of design pattern programming is,
Program to the Interface and not the implementation….
In order to see both how abstractions are used and how relations work in the n the Factory Method pattern, Figure 2 shows code snippets related to each of the participants (classes and relationships).
In looking at Figure 2 code snippets, notice how many times that Creator or Product are used. Both reflect the wholly abstract interfaces in the program. By making references to the interfaces (or abstract classes), the binding between the Client and the requests is very loose. By having loose binding through abstractions, the developer can better update and change the program. The only part of the objects exposed are those that are required. If the concrete products change, the Client is not tightly bound to the concrete elements because the requests hold references to the abstract interfaces and not the concrete participants. (Read on to see how these are all put together!)