In the first part of this series we talked about cohesion and coupling, their importance and origin, and what are Software Design Patterns. In this second part, we'll see a summarization of 5 Design Patterns of [Gamma, et al] to achieve Low Coupling (or Loose Coupling) between classes.
The book "Design Patterns: Elements Of Reusable Object-Oriented Software" [Gamma et al] is one of the most famous books on Design Patterns. It is commonly called "The GOF book" (Gang Of Four), and was written in collaboration by Erich Gamma (JUnit, Eclipse and Visual Studio team), Richard Helm, Ralph Johnson (Smalltalk pioneer, OOPSLA) and John Vlissides. It contains a small theory part and a big catalog of patterns, which applies to any type of object-oriented software (not just Enterprise, Web or Telecom Applications). The patterns are divided in Creational, Structural and Behavioral. We'll talk next about the Creational Patterns, that help reducing coupling in an object-oriented software.
The Creational Patterns
Creational Patterns can be of types class or object, which uses respectively inheritance and delegation to another object to instatiate concrete objects. They define inferfaces (or abstract classes) that the whole system knows and interacts, and hides how instances of these interfaces are created (which can be in a static hard coded way or dynamically).
Sometimes you have a group of objects that operate together to bring some functionality, and these objects must be decoupled from the "client" application, so they can be changed as a group by other objects. An example of this are components of a Graphical User Interface, that can have groups of concrete classes representing visual components with differing layouts, styles and even user interaction functionality, and are grouped as a components library. Another example would be a group of classes for sending data through a network using a chosen protocol (TCP, UDP, etc) - the creation of header objects, a streamer, a configuration object, etc could be provided by an Abstract Factory. The parts of the application which USES this functionality would have an object of unknown concrete type, but known supertype (interface or abstract class) that is the Abstract Factory, that can be used to create several components of diferent types to accomplish a task.
The Abstract Factory pattern is useful to facilitate the change (statically or dynamically) of groups of components, that are used and created in different places of the application, by abstracting this creation in an object called Factory. The point here is NOT to hide the concrete class only, but to provide an object that can be used to create an unknown concrete class WHENEVER the application class needs it, and still having a well specified contract to interact with any type of concrete classes.
Some of you might think that this is useless as you still have to create the object of concrete class of the Abstract Factory somewhere, and then the static code that cites the concrete class would still be present and there would be no decoupling. This is wrong. First, the coupling would be reduced to specific points in the software IF it is specified statically. But there could be a visual component that configures the software, or a field in a database or XML that specifies which concrete factory should be used - and absolutely no coupling in the code. Actually, this is the most common scenario because of a pattern named Dependency Injection, which is getting very popular, and we'll see about it in part 3 of this series of posts.
A good real-world example of the Abstract Factory is the JDBC library of Java SE. The center interface of the library is java.sql.Connection, which acts like an Abstract Factory. It is created (a concrete object) through DriverManager class, that decides in runtime which object to create - one to access a PostgreSQL or a Oracle one, for example. The java.sql.Connection class alows the application code to create java.sql.Statement objects, java.sql.Array objects and others, that are used together to query data in a relational database.
The Factory Method is a pattern to create a functionality in a class while delegating the instatiation of the related objects to subclasses of the first one.
Example: imagine you're creating a code that receives a document from a message queue, checks for it's validity, generates another document in a specified format and sends it somewhere. But according to the document origin, you want to generate a PDF and send it as an e-mail, or you want to generate a XML and save it on a file, or you want to generate a JSON and put it as a document on a NoSQL. For that, you could create the functionality as an abstract class (let's name it DocumentProcessor), specify interfaces that generates the document and saves it somewhere (like DocumentGenerator and DocumentStorage) and let the creation of these objects in abstract methods (no implementation). Then you would create classes that inherit from DocumentProcessor and implement those methods that should create concrete objects and actually create those, according to the result you want. Of course you would need a way to create the concrete DocumentProcessor according to data from the message queue. But this class would not need to know about the objects that DocumentProcessor needs to function properly.
This pattern is useful when a class wants to provide a functionality but can't antecipate the objects it must create, or it wants to provide a generic functionality that can be used for several scenarios by changing the concrete objects it uses. It is important to say that this class can provide default implementations, and can even not be an abstract class. This can be used for facilitating a future development of the software (but I don't think this is worth, as I would prefer refactoring).
A real-world example of Abstract Method is in the class java.util.Calendar, of the Java SE. The method getInstance() creates an object that is used by the class java.util.Calendar to obtain the current time in the default time zone.
The Builder pattern is for complex object creation only. Let's say for example that you want to create a document in a specific format (XML, PDF or JSON) and the creation must follow a specific order, independenly of the document format. For that you could create a Builder interface with methods for each step of the creation and implement them in concrete classes. And the actual order (the call for each method of Builder) would be in a Director class, which would not create the concrete Builder, but receive it through a constructor. So the "Client" class (the application class) that wants a document in a specific format would create a concrete Builder, feed it to a new Director which would execute the steps of creation, and then get the result object (in this case the document) from the builder directly.
This pattern allows the developer to separate a generic instatiation PROCESS (sequence of steps) from concrete creators, classes and the way to obtain the result. For example, one could have a Director that creates a document with a summary of an Invoice, and another that creates a detailed document representing the Invoice. In both cases, the same builders would be used, which provides methods for creating document segments containing Invoice data, in a specific format (PDF, XML or JSON).
The Factory Method could be used in the example above instead of the Builder. The diference between them is the existence of the Director class. When using Builder, one can have multiple Director classes that creates objects in different ways. It surely creates a more complex set of interactions and objects, so it should be used only when needed. According to [Gamma et al], it is wiser to start with a simpler pattern and if needed, refactor to the Builder pattern.
The prototype is used to create a copy of an existing object (the prototype) without knowing it's concrete type and without using an external class (like a Factory).
The traditional example is a GUI which is a document editor, and provides types of graphical elements to be placed in the document. This graphical elements are represented by components which are/have prototypes (objects that follow the Prototype pattern), that are used to create new graphical elements in the document. So the objects that handle the creation of these objects in the document would not need to know which type the component represents/concretely is.
The singleton is one of the easiest Design Patterns and one of the most cited. It ensures that there is only a single instance of a class, and that this instance is obtainable from only a single point of access (generally one unique method of the class).
Some classes, specially when they relate to a resource like a printer or a file, need to have exactly one instance. Sometimes you want to create an object to manage others, for example a pool of PDFGenerators that run in multiple threads. This "managers" also almost always must have a unique object, and more than that, this object must be accessible to any part of the application.
The common way to implement a Singleton is to create a method getInstance() which creates and stores the unique instance if it does not exist, and returns it from the class reference (a static field). Also, the constructor is set to private, so a new object can't be created by accident (when the programming language allows it).
[OODesign] Decoupling Object Instantiation Part 3 – Inversion Of Control and Dependency Injection
[Gamma et al] Gamma et al. “Design Patterns: Elements of Reusable Object Oriented Software”, 1995, Addison-W esley.
[Wiki AbsFact] "Abstract Factory pattern". Obtained in http://en.wikipedia.org/wiki/Abstract_factory_pattern.