|












| |
GOF Design Patterns and OOP Notes
A pattern addresses a recurring design problem that arises
in specific design situations and presents a solution to it” (Buschmann, et. al.
1996)
Object Oriented Programming Best Practices
| Creational Design Patterns |
Factory Method
Methods, which create an instance of another class is known as a Factory
Method. A class (Factory Class) can contain one or more Factory Methods.
Factory Methods can be static or non-static. We can create a concrete
Factory class and its sub-classes can create appropriate instances. The
Factory Method is only responsible for creating objects. Once they create &
return an object, they don’t have any control over object’s life time. You
should consider using a Factory pattern to reduce coupling and to create
multiple objects at run time based on some inputs or conditions. Unlike
constructors, factory methods are not required to create a new object each
time they are invoked. Factory methods can encapsulate the logic required to
return a singleton instance of the class requested, or they can return an
instance of the requested class from a pool of instances. The base Factory
class is abstract.The Concrete classes override getMyClass() method to
return a particular type of object.

Examples of factory method in JDK:
- public static Runtime getRuntime() of Runtime class.
- createStatement() of Connection class (java.sql) |
Abstract Factory
The Abstract Factory Method (AFM) is one level abstraction higher than the
Factory Method pattern. AFM is useful when we want to return one of several
related classes of objects, each of which can return several different
objects on request. AFM can provide more than of type of objects.An abstract
factory provides an interface for creating families of related objects
without specifying their concrete classes. Abstract Factory provide a single
interface to Clients to use, when they need to create a family of related
objects. The Abstract factory publishes an interface for creating abstract
products. But the concrete subclasses actually provide the concrete
products.Accessing an abstract factory is normally done through a static
method on the Abstract Factory class.Whenever we need new kind of products
to be created, we just want to make new concrete factory classes. To change
a complete family of products is easy. Just change the factory, the client
uses. AFM helps to increase the overall flexibility of an application. This
flexibility manifests itself both during design & run time. During design
time, you do not have to predict all future uses for an application.
Instead, you create the generic frameworks and then develop implementations
independently from the rest of the application. At run time, the application
can easily integrate new features and resources. Use AFM when you want your
system to be independent from the products it uses. This involves being
independent from the creation, composition, and representation of the
products. You want the ability to interchange the type of family of products
the system uses.
Whenever the application wants to deal multiple Operating Systems, Multiple
Databases, Multiple Persistent Mechanisms, multiple document types, multiple
image types etc. Used in JDBC, Java Mail, Swing pluggable L&F, AWT toolkit,
DAO. |
Builder
Builder patterns allows a client to construct a complex object by specifying
only its type & context. The Client is totally shielded from the details of
actual construction process. In builder pattern, the client is given the
choice to create the type of object that he/she wants. Use builder pattern
when The algorithm for creating a complex object should be independent of
the parts that make up the object and how they're assembled or when a
program is required to produce multiple external representation of the same
data. Builder pattern allows us to vary a Product’s internal representation. |
Prototype
The Prototype pattern is used when creating an instance of a class is very
time-consuming or complex in some way. In that case, instead of creating
more instances from scratch, its better to make copies of the available
instance and modifying them as per requirement. The most important
requirement for objects to be used as Prototype is that they have a method,
typically called clone(), which returns a new object (copy of the original
object). In shallow copy the internal object is not cloned whereas in deep
copy even the internal object which is being composed, is also cloned. By
default clone method returns a shallow copy. We have to override ‘clone()’
method, if we are interested in deep cloning. Only instances of those
classes, which implements ‘cloneable’ interface can be cloned. The ‘clone()’
method always returns an object of type ‘Object’. So we must cast it to the
actual type of object. Prototype pattern is useful for dynamically adding &
removing objects at run-time. It reduces the need of sub classing and helps
to reduce the number of classes.
The Prototype pattern is used when creating an instance of a class is very
time-consuming or complex in some way like getting some data from Database
or across the network. |
Singleton
The Singleton pattern ensures that a class has only one instance. Provides a
global point of access to that instance.

Constructor is ‘PRIVATE’. This ensures that no other code in your
application will be able to create an instance of this class, by using the
constructor directly. Using a static method, which returns an object. Static
variable, used for holding the created instance. If the instance is already
there, the static method do not create a second one, instead returns the
already created one.When multiple threads are introduced, you must protect
the getInstance() method through synchronization. If the getInstance()
method is not protected against synchronization, it is possible to return
two different instances of the Singleton object. Refer to Double Checked
Lock (DCL) programming pattern and ThreadLocal implementation for better
singleton implementation in a multithreaded environment. |
|
Structural
Design Patterns |
The Adapter Pattern The Adapter pattern is used to
convert the programming interface of one class into that of another. We use
adapters whenever we want unrelated classes to work together in a single
program. The concept of an adapter is thus pretty simple; we write a class
that has the desired interface and then make it communicate with the class
that has a different interface. There are two ways to do this: by
inheritance, and by object composition. In the first case, we derive a new
class from the nonconforming one and add the methods we need to make the new
derived class match the desired interface. The other way is to include the
original class inside the new one and create the methods to translate calls
within the new class. These two approaches, termed class adapters and object
adapters are both fairly easy to implement in Java. |
The Bridge Pattern At first sight, the Bridge
pattern looks much like the Adapter pattern, in that a class is used to
convert one kind of interface to another. However, the intent of the Adapter
pattern is to make one or more classes’ interfaces look the same as that of
a particular class. The Bridge pattern is designed to separate a class’s
interface from its implementation, so that you can vary or replace the
implementation without changing the client code. |
The Composite
Pattern Frequently programmers develop systems in which a component
may be an individual object or it may represent a collection of objects. The
Composite pattern is designed to accommodate both cases. You can use the
Composite to build part-whole hierarchies or to construct data
representations of trees. In summary, a composite is a collection of
objects, any one of which may be either a composite, or just a primitive
object. In tree nomenclature, some objects may be nodes with additional
branches and some may be leaves. |
The Façade
Pattern Frequently, as your programs evolve and develop, they grow
in complexity. In fact,for all the excitement about using design
patterns, these patterns sometimes generate so many classes that it is
difficult to understand the program’s flow. Furthermore, there may be a
number of complicated subsystems, each of which has its own complex interface.The Façade pattern allows you to simplify this complexity by
providing a simplified interface to these subsystems. This simplification
may in some cases reduce the flexibility of the underlying classes, but
usually provides all the function needed for all but the most
sophisticated users. These users can still, of course, access the
underlying classes and methods. |
The Proxy Pattern The
Proxy pattern is used when you need to represent an object that is complex
or time consuming to create, by a simpler one. If creating an object is
expensive in time or computer resources, Proxy allows you to postpone this
creation until you need the actual object. A Proxy usually has the same
methods as the object it represents, and once the object is loaded, it
passes on the method calls from the Proxy to the actual object. There are
several cases where a Proxy can be useful: 1. If an object, such as a
large image, takes a long time to load. 2. If the object is on a remote
machine and loading it over the network may be slow, especially during
peak network load periods. 3. If the object has limited access rights,
the proxy can validate the accesspermissions for that user. |
| The Decorator
pattern, a class that surrounds a given class, adds new
capabilities to it, and passes all the unchanged methods to the underlying
class. |
|
Behavioral
Design Patterns |
The Template
Method Whenever you write a parent class where you leave one or
more of the methods to be implemented by derived classes, you are in essence
using the Template pattern. The Template pattern formalizes the idea of
defining an algorithm in a class, but leaving some of the details to be
implemented in subclasses. In other words, if your base class is an abstract
class, as often happens in these design patterns, you are using a simple
form of the Template pattern. |
The Chain of Responsibility The Chain of Responsibility
pattern allows a number of classes to attempt to handle a request, without
any of them knowing about the capabilities of the other classes. It provides
a loose coupling between these classes; the only common link is the request
that is passed between them. The request is passed along until one of the
classes can handle it. |
The Command Pattern The Chain of
Responsibility forwards requests along a chain of classes, but the Command
pattern forwards a request only to a specific object. It encloses a
request for a specific action inside an object and gives it a known public
interface. It lets you give the client the ability to make requests
without knowing anything about the actual action that will be performed,
and allows you to change that action without affecting the client program
in any way. |
The Iterator Pattern The Iterator
is one of the simplest and most frequently used of the design patterns.
The Iterator pattern allows you to move through a list or collection of
data using a standard interface without having to know the details of the
internal representations of that data. In addition you can also define
special iterators that perform some special processing and return only
specified elements of the data collection. |
The Visitor Pattern The Visitor
pattern turns the tables on our object-oriented model and creates an
external class to act on data in other classes. This is useful when you
have a polymorphic operation that cannot reside in the class hierarchy for
some reason.. For example, the operation wasn’t considered when the
hierarchy was designed, or because it would clutter the interface of the
classes unnecessarily. |
The Mediator Pattern When a
program is made up of a number of classes, the logic and computation is
divided logically among these classes. However, as more of these isolated
classes are developed in a program, the problem of communication between
these classes become more complex. The more each class needs to know about
the methods of another class, the more tangled the class structure can
become. This makes the program harder to read and harder to maintain. Further,it can become difficult to change the program, since any change
may affect code in several other classes. The Mediator pattern addresses
this problem by promoting looser coupling between these classes. Mediators
accomplish this by being the only class that has detailed knowledge of the
methods of other classes. Classes send inform the mediator when changes
occur and the Mediator passes them on to any other classes that need to be
informed. |
The State Pattern The State
pattern is used when you want to have an object represent the state of
your application, and switch application states by switching objects. For
example, you could have an enclosing class switch between a number of
related contained classes, and pass method calls on to the current
contained class. Design Patterns suggests that the State pattern
switches between internal classes in such a way that the enclosing object
appears to change its class. In Java, at least, this is a bit of an
exaggeration, but the actual purpose to which the classes are put can
change significantly. Many programmers have had the experience of
creating a class that performs slightly different computations or displays
different information based on the arguments passed into the class. This
frequently leads to some sort of switch or if-else statements inside the class that determine which behavior to carry
out. It is this inelegance that the State pattern seeks to replace. |
The Strategy
Pattern The Strategy pattern is much like the State pattern in
outline, but a little different in intent. The Strategy pattern consists
of a number of related algorithms encapsulated in a driver class called
the Context. Your client program can select one of these differing
algorithms or in some cases the Context might select the best one for you.
The intent is to make these algorithms interchangeable and provide a way
to choose the most appropriate one. The difference between State and
Strategy is that the user generally chooses which of several strategies to
apply and that only one strategy at a time is likely to be instantiated
and active within the Context class. By contrast, as we have seen, it is
possible that all of the different States will be active at once and
switching may occur frequently between them. In addition, Strategy
encapsulates several algorithms that do more or less the same thing, while
State encapsulates related classes that each do something somewhat
different. Finally, the concept of transition between different states is
completely missing in the Strategy pattern. |
The Observer Pattern The Observer
pattern assumes that the object containing the data is separate from the
objects that display the data, and that these display objects observe changes in that data. When we implement the Observer pattern, we
usually refer to the data as the Subject and each of the displays as
Observers. Each of these observers registers its interest in the data by
calling a public method in the Subject. Then, each observer has a known
interface that the subject calls when the data
change. |
|
|
|
Object Oriented Programming Best Practices
|
Interface with Interfaces Use interfaces as the glue
throughout your code instead of classes: define interfaces to describe the
exterior of objects (i.e. their Type) and type all variables, parameters,
and return values to interfaces. The most important reason to do this is
that interfaces focus on the client’s needs: interfaces define what
functionality a client will receive from an Object without coupling the
client to the Object’s implementation. This is one of the core concepts to
OO. |
Create Different Interfaces for Different Types of
Clients Provide different interfaces to support different types of
clients and to prevent exposing responsibilities to clients who should not
see it. Provides a more understandable system for a particular client’s
perspective and makes maintenance impacts more visible. |
Use Interfaces over Abstract Classes If you can conceive of
someone else implementing a class's functionality differently, define an
interface, not an abstract class. Generally, use abstract classes only
when they are ``partially abstract''; i.e., they implement some
functionality that must be shared across all subclasses. Interfaces are
more flexible than abstract classes. They support multiple inheritance and
can be used as `mixins' in otherwise unrelated classes. |
Rarely declare a class final Declare a class as final only
if it is a subclass or implementation of a class or interface declaring
all of its non-implementation-specific methods. (And similarly for final
methods). Making a class final means that no one ever has a chance to
reimplement functionality. Defining it instead to be a subclass of a base
that is not final means that someone at least gets a chance to subclass
the base with an alternate implementation. Which will essentially always
happen in the long run. |
| Minimize statics (except for static final constants). Static
variables act like globals in non-OO languages. They make methods more
context-dependent, hide possible side-effects, sometimes present
synchronized access problems. and are the source of fragile,
non-extensible constructions. Also, neither static variables nor methods
are overridable in any useful sense in subclasses. |
Use Factories for Creating Objects Use Factories and Factory
methods for "public" object construction: have an object be responsible
for construction instead of having clients directly call "new AClass()".
The reason to use factory creation methods instead of straight
constructors is because they: Allow more flexibility in "creating" a new
object: the implementation can just reuse an existing object if the
semantics make sense. Can have better names: "newTimeNow()" and
"newTimeFromSeconds(...)" instead of "new Time()" and "new Time(...)"
Provide better separation between interface and implementation: we can
document the factory method in an interface. Naturally flow into more
sophisticated factory designs.The implementation can take advantage of
inheritance since it is a "normal" object method. |
| Never declare instance variables as public. The standard OO
reasons. Making variables public gives up control over internal class
structure. Also, methods cannot assume that variables have valid values.
|
| All data should be hidden within its class. |
| Keep things as “private as possible.” Once you publicize an
aspect of your library (a method, a class, a field), you can never take it
out. If you do, you’ll wreck somebody’s existing code, forcing them to
rewrite and redesign. If you publicize only what you must, you can change
everything else with impunity, and since designs tend to evolve this is an
important freedom. In this way, implementation changes will have minimal
impact on derived classes. Privacy is especially important when dealing
with multithreading—only private fields can be protected against
un-synchronized use. |
| Users of a class must be dependent on its public interface, but a
class should not be dependent on its users. |
| Do not change the state of an object without going through its public
interface. |
| Minimize the number of messages in the protocol of a class. |
| Do not clutter the public interface of a class with things that users
of that class are not able to use or are not interested in using. |
| Keep related data and behavior in one place. Spin off non-related
information into another class. |
| Distribute system intelligence horizontally as uniformly as possible,
i.e. the top level classes in a design should share the work uniformly.
|
| Do not create god classes/objects in your system. Be very suspicious
of an abstraction whose name contains Driver, Manager, System, or
Subsystem. |
| In applications which consist of an object-oriented model interacting
with a user interface, the model should never be dependent on the
interface. The interface should be dependent on the model. |
| Inheritance should only be used to model a specialization hierarchy.
|
| All data in a base class should be private, i.e. do not use protected
data. |
| Theoretically, inheritance hierarchies should be deep, i.e. the deeper
the better. Pragmatically, inheritance hierarchies should be no deeper
than an average person can keep in their short term memory. A popular
value for this depth is six. |
| All abstract classes must be base classes. All base classes should be
abstract classes. |
| Factor the commonality of data, behavior, and/or interface as high as
possible in the inheritance hierarchy. |
| If two or more classes only share common data (no common behavior)
then that common data should be placed in a class which will be contained
by each sharing class. |
| If two or more classes have common data and behavior (i.e. methods)
then those classes should each inherit from a common base class which
captures those data and methods. |
| If two or more classes only share common interface (i.e. messages, not
methods) then they should inherit from a common base class only if they
will be used polymorphically. |
| If you have an example of multiple inheritance in your design, assume
you have made a mistake and prove otherwise. |
| Whenever there is inheritance in an object-oriented design ask
yourself two questions: 1) Am I a special type of the thing I'm inheriting
from? and 2) Is the thing I'm inheriting from part of me? |
| Whenever you have found a multiple inheritance relationship in a
object-oriented design be sure that no base class is actually a derived
class of another base class, i.e. accidental multiple inheritance. |
What are some alternatives to
inheritance? Delegation is an alternative
to inheritance. Delegation means that you include an instance of another
class as an instance variable, and forward messages to the instance. It is
often safer than inheritance because it forces you to think about each
message you forward, because the instance is of a known class, rather than
a new class, and because it doesn't force you to accept all the methods of
the super class: you can provide only the methods that really make sense.
On the other hand, it makes you write more code, and it is harder to
re-use (because it is not a subclass). |
The Utility Class idiom A utility class contains only public static
methods and is not meant to be instantiated. Utility classes are easily
abused and can lead to procedural programming. However, Bloch pointed out
two valid uses of this idiom. You should use a utility class to act on
collections of primitives and collections of objects that implement
interfaces. java.util.Collections serves as an example of a
properly designed utility class. |
| Watch for long method definitions. Methods should be brief,
functional units that describe and implement a discrete part of a class
interface. A method that is long and complicated is difficult and
expensive to maintain, and is probably trying to do too much all by
itself. If you see such a method, it indicates that, at the least, it
should be broken up into multiple methods. It may also suggest the
creation of a new class. Small methods will also foster reuse within your
class. (Sometimes methods must be large, but they should still do just one
thing.) |
Return Immutables From Accessor Methods Many
accessor methods need to return values which are references to objects
which represent a part of the state of the called object; directly
returning the state in this form will expose the internals of the called
object, and the caller will have the ability to modify that state
unpredictably. |
Copy Mutable Parameters If an object has to use a
mutable object as a ValueObject, operations on the mutable value can
change the object's internal state without its knowledge and can cause
it's state to become inconsistent. Therefore: an object
that holds mutable objects as state must
ReturnNewObjectsFromAccessorMethods. Additionally, it must make private
copies of mutable objects that are passed to it and that it needs to store
internally. (by making use of use cloning) |
Object Pooling Don't do it. Outside of some cases
where you are actually pooling the resource held by the object and not the
object itself (e.g. thread pools, database connections, huge bitmaps,
etc.), object pooling is not worth doing anymore. Object allocation is now
so fast that the necessary synchronization required by an object pool
implementation is slower than simply allocating new objects. |
| Choose interfaces over abstract classes. If you know something
is going to be a base class, your first choice should be to make it an
interface, and only if you’re forced to have method definitions or member
variables should you change it to an abstract class. An interface talks
about what the client wants to do, while a class tends to focus on (or
allow) implementation details. |
|