The GoF book defines the Factory Method pattern in terms of an ICreator interface that defines a virtual function, CreateIProduct(). The virtual function CreateIProduct() returns a base class, IProduct. So, classes that derive from ICreator implement CreateIProduct() to return a subclass of IProduct. In other words, a SubclassOfCreator would create a SubclassOfProduct.
Like the Abstract Factory pattern, this enforces object cohesion – the SubclassOfCreator creates only the types that it can work with. It also allows for extensibility, because the framework is only providing the ICreator and IProduct interfaces. The client code will derive from ICreator and IProduct, which eliminates the need for client-specific behaviors in the framework’s code.
We’ll start the discussion of design patterns with the object creation patterns. First up is the Singleton pattern. Conceptually, this is used when you want exactly one instance of an object. A common example is a logger. Sometimes an application wants all its components to log data to the same destination. So, developers might create a Singleton logger, then all the components can easily get a handle to its instance and use its API. But the Singleton pattern has significant drawbacks, and there’s usually better methods for handling situations where you want a Singleton.
This is the first in a series of posts I will write about design patterns.
Design patterns in software development have been heavily influenced by the work of Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, known as the Gang of Four (GoF). They literally wrote the book on patterns, Design Patterns: Elements of Reusable Object-Oriented Software. In this book, the authors describe patterns for managing object creation, composing objects into larger structures, and coordinating control flow between objects. Since publication, other developers have identified and described more patterns in practically every area of software design. Try googling your favorite software topic + “design patterns” to see what kind of patterns other developers have identified and described: android design patterns, embedded design patterns, machine learning design patterns, etc.
It’s very useful to know about the patterns in abstract, even if you don’t know the details of a particular pattern. As the authors state, knowing the patterns helps developers identify and use the “right” design faster. Knowing the patterns provides these benefits to the developer:
- They describe common problems that occur in software development. As a developer, especially a new developer, it’s easy to think of every problem as completely unique to the program that you’re writing. But very often, they are unique only because of poor modeling or simply lack of experience. Simply knowing common problems can help a developer model a system in terms of those problems, which often reduces the size, number, and complexity of the problems that remain to be solved.
- They are considered “best known methods” for solving typical/frequent problems that arise in programming & architecture. Knowing the “best known method” for solving a problem eliminates a lot of thought, effort, and time devoted to solving it, which reduces the time that a developer must spend on a particular problem.
- Knowledge of the patterns simplifies & clarifies communication between developers when talking about a particular problem or solution. When a developer who is familiar with design patterns hears “I used the singleton pattern on the LogFile class,” the developer immediately knows that (if implemented correctly) there will only be one or zero instances of the LogFile class living in the program at one time.
When to use it
It’s pretty easy to describe when to use a pattern – whenever your program contains the exact problem that is solved by one of the patterns. They can even be used if your program contains a similar problem to that solved by one of the patterns, but in this case, the implementation of the pattern may need to be modified to fit the particulars of your program.
However, it’s not always obvious your software’s problem(s) can be solved by a GoF pattern. In other words, the program may be such a mess that it needs to be refactored simply to transform a problem into one that can be solved with a GoF pattern. Hopefully by learning about the patterns, you’ll be able to recognize non-obvious applications in your own software.
I’ll cover the patterns by subject, and within a subject I’ll try to cover what I feel are the most broadly applicable patterns first. Stay updated by following me on RSS, linkedin, or twitter (@avitevet)!