Home > Articles > Software Development & Management

  • Print
  • + Share This
This chapter is from the book Summary

Summary

While reviewing the Bridge pattern, I looked at a problem where there were two variations in the problem domain—shapes and drawing programs. In the problem domain, each of these varied. The challenge came when trying to implement a solution based on all the special cases that existed. The initial solution, which naively used inheritance too much, resulted in a redundant design that had tight coupling and weak cohesion, and was thus difficult to maintain.

You learned the Bridge pattern by following the basic strategies for dealing with variation:

  • Find what varies and encapsulate it.
  • Favor aggregation over inheritance.

Finding what varies is always a good step in learning about the problem domain. In the drawing program example, I had one set of variations using another set of variations. This indicates that the Bridge pattern will probably be useful.

In general, you should identify which patterns to consider by matching them with the characteristics and behaviors in the problem domain. By understanding the whys and whats of the patterns in your repertoire, you can be more effective in picking the ones that will help you. You can select patterns to consider before deciding how the pattern’s implementation will be done.

If you use9 the Bridge pattern, the design and implementation are more robust and better able to handle changes in the future.

Although I focused on the Bridge pattern during the chapter, it is worth pointing out several object-oriented principles that are used in the Bridge pattern.

Concept

Discussion

Objects are responsible for themselves

I had different kinds of Shapes, but all drew themselves (via the draw method). The Drawing classes were responsible for drawing elements of objects.

Abstract class

I used abstract classes to represent the concepts. I actually had rectangles and circles in the problem domain. The concept “shape” is something that lives strictly in our head, a device to bind the two concepts together; therefore, I represent it in the Shape class as an abstract class. Shape will never get instantiated because it never exists in the problem domain (only Rectangles and Circles do). The same thing is true with drawing programs.

Encapsulation via an abstract class

I have two examples of encapsulation through the use of an abstract class in this problem:

  • A client dealing with the Bridge pattern will have only a derivation of Shape visible to it. However, the client will not know what type of Shape it has. (It will be just a Shape to the client.) Thus, I have encapsulated this information. The advantage of this is if a new type of Shape is needed in the future, it does not affect the client object.
  • The Drawing class hides the different drawing derivations from the Shapes. In practice, the abstraction may know which implementation it uses because it might instantiate it. See page 155 of the Gang of Four book for an explanation as to why this might be a good thing to do. However, even when that occurs, this knowledge of implementations is limited to the abstraction's constructor and is easily changed.

One rule, one place

The abstract class often has the methods that actually use the implementation objects. The subclasses of the abstract class call these methods. This allows for easier modification if needed, and allows for a good starting point even before implementing the entire pattern.

Testability

Imagine writing tests for the shapes and drawing programs with both our original solution and our later solution. For example, suppose you have N shapes and M implementations. The first solution would require N*M tests. The second solution only requires M+N tests: First test the M implementations, and then test the N shapes with arbitrarily chosen implementations (because all of the shapes work with all of the implementors in exactly the same way).

  • + Share This
  • 🔖 Save To Your Account