Design Patterns in Java Summary v2
Design Patterns in Java Summary v2
Creational Design Patterns
Design Patterns in Java
• Think of builder pattern when you have a complex constructor or an object is built
in multiple steps.
class Builder
ConcreteBuilder
Product
+ build(): void
+ getProduct(): Product
Director (Role played by Client)
often given as examples of builder pattern.
• In my humble opinion they can be given as examples of builder pattern, but with an understanding that they don’t
match 100% with GoF definition. These classes do allow us to build final object in steps, providing only a part of final
object in one step. In this way they can be thought of as an implementation of builder pattern.
• So a StringBuilder satisfies the intent/purpose of builder pattern. However as soon we start looking at structure of
representations of product interface using same steps.
Creational Design Patterns
Design Patterns in Java
• We can pass an argument to this method to indicate product type and/or additional arguments to help create objects
class SimpleFactory
Client «static»
Product
SimpleFactory
+ getProduct(String): Product
«implementationclass» «implementationclass»
ProductA ProductB
(*Many examples advertised online as “Factory Method” are actually Simple Factories.)
Creational Design Patterns
Design Patterns in Java
Product Creator
example of a factory method.
• Remember, the most defining characteristic of factory method pattern is “subclasses providing the actual instance”.
So static methods returning object instances are technically not GoF factory methods.
Creational Design Patterns
Design Patterns in Java
not possible (object is supplied to your code).
• In Java we typically implement this pattern with clone method.
• Objects which have a majority of their state as immutable are good candidates for prototypes.
• When implementing clone method pay attention to the requirement of deep or shallow copy of object
state.
• Also we’ve to insure that clone is “initialized”; that is appropriate states are reset before returning the
copy to outside world.
class Prototype
«abstract»
Client Prototype
+ clone(): Prototype
ConcretePrototypeA ConcretePrototypeB
+ clone(): ConcretePrototypeA + clone(): ConcretePrototypeB
• Actually the Object.clone() method is an example of a prototype!
• This method is provided by Java and can clone an existing object, thus allowing any object to act as
a prototype. Classes still need to be Cloneable but the method does the job of cloning object.
• We also use the same method to implement our own prototype, as it is a well known method and
has same meaning as we want in a prototype method.
Creational Design Patterns
Design Patterns in Java
• When you have multiple sets of objects where objects in one set work together then you can use
abstract factory pattern to isolate client code from concrete objects & their factories.
• Abstract factory itself uses factory method pattern and you can think of them as objects with
multiple factory methods.
• Adding a new product type needs changes to base factory and all its implementations.
• Concrete factories can be singleton as we need only one instance of them in code.
• We provide client code with concrete factory instance. Factories can be changed at runtime.
Client
«abstractfactory»
ResourceFactory
+ createInstance(capacity): Instance
«abstract_product»
+ createStorage(inMib): Storage
Instance
+ start(): void
+ stop(): void
+ attachStorage(storage): void
«concrete_product»
«concrete_product»
Ec2Instance
GoogleComputeEngineInstance
«concrete_factory»
GoogleCloudResourceFactory «concrete_factory»
AwsResourceFactory «abstract_produ...
+ createInstance(capacity): Instance Storage
+ createStorage(inMib): Storage + createInstance(capacity): Instance
+ createStorage(inMib): Storage
+ getId(): String
«concrete_product» «concrete_product»
S3Storage GoogleCloudStorage
“Amazon Web Services” Product Family “Google Cloud Platform” Product Family
Implementations of Abstract Factory
• However this implementation doesn’t match 100% with the UML of abstract factory from GoF. The class has a static
newInstance() method which returns actual factory class object.
• The newInstance() method however uses classpath scanning, system properties, an external property file as ways to
find the factory class & creates the factory object. So we can change the factory class being used, even if this is a
static method.
• Another great example is the java.util.prefs.PreferencesFactory interface which matches more closely with the UML
we studied.
Creational Design Patterns
Design Patterns in Java
• In Java we achieve this by making constructor private, this also prevents inheritance & providing a public static
method which returns the singleton instance
• Implementation wise we have two broad choices –
1. In eager loading singleton, we create instance as soon as class is loaded by classloader.
2. In lazy loading singleton, we defer creation until some code actually requests the instance.
• Always prefer the eager loading instance unless creation cost is high and start‐up time impact is noticeable.
• There are very few situations where a Singleton is really a good choice.
• Application configuration values can be tracked in a singleton. Typically these
are read from file at start and then referred to by other parts of application.
• Logging frameworks also make use of Singleton pattern.
• Spring framework treats all beans by default as singletons. In spring we don’t
have to make any changes to ensure single instance, Spring handles that for us.
• The java.lang.Runtime class in standard Java API is a singleton.
Creational Design Patterns
Design Patterns in Java
them with object pool.
• Typically objects that represent fixed external system resources like threads, connections or other system resources are good candidates for pooling
class ObjectPool
«use»
ObjectPool AbstractReusable
Client + getReusable() + operation()
+ releaseReusable()
ConcreteReusable
- state
+ operation()
+ reset()
well, otherwise release operation will be costly.
• Pool must handle synchronization issues efficiently and reset object state before adding them to pool for reuse.
• Client code must release pooled objects back into the pool so they can be reused. Failing to do so will break the system. Thread
pools can work around this since the a thread can know when its work is done.
• Difficult to optimize as pools are sensitive to system load at runtime (demand of pooled objects).
• Pools are good choice when the pooled objects represent a fixed quantity of externally available resource like thread or a
connection.
• If you create objects when pool is empty then we have to make sure that pool size is maintained or else we can end up with large
pool
Reusable Product
efficient & have access to more memory now.
• However it is still a very common pattern when we are interacting with external resources like threads, connections.
• java.util.concurrent.ThreadPoolExecutor is an example of object pool pattern which pools threads. Even though we can
directly use this class, you’ll often use it via ExecutorService interface using method like Executors like
newCachedThreadPool().
dbcp package is an example of object pool pattern which pools database connections. This pool is commonly created
and exposed via JNDI or as a Spring bean in applications.
• We have an existing object with required functionality but the client code is expecting a
• A class adapter is one where adapter inherits from class of object which is to be adapted and
implements the interface required by client code. This adapter type should be avoided.
• An object adapter uses composition over inheritance. It’ll implement the target interface and
use an adaptee object composition to perform translation. This allows us to use subclasses of
adaptee in adapter.
In-A-Hurry Summary
class Adapter
Class Adapter
«interface» Adaptee
Client Target
+ myOperation(): void
+ operation(): void
class AdapterObject
Adapter
operation
Object Adapter
+ operation(): void
this.myOperation()
«interface»
Target
Client Adaptee
«use» + operation(): void
+ myOperation(): void
#adaptee
ObjectAdapter
+ operation(): void
operation
adaptee.myOperation()
In-A-Hurry Summary
Target Interface Our existing class (Adaptee)
• These classes adapt existing InputStream/OutputStream object to a Reader/Writer interface.
Structural Design Patterns
Design Patterns in Java
• We use bridge pattern when we want our abstractions and implementations to be
decoupled.
• Bridge pattern defines separate inheritance hierarchies for abstraction & implementations
and bridge these two together using composition.
• Implementations do not HAVE to define methods that match up with methods in abstraction.
It is fairly common to have primitive methods; methods which do small work; in
implementor. Abstraction uses these methods to provide its functionality.
class Bridge
«abstract» Implementor
Client Abstraction
«use» + step1(): void
+ operation(): void + step2(): void
RefinedAbstraction
ConcreteImplementorA ConcreteImplementorB
+ step1(): void + step1(): void
+ step2(): void + step2(): void
Refined Abstraction Concrete Implementor
dropping jar files in classpath. The client code using slf4j API remains unaffected. So the abstraction (slf4j API) can vary independent
of implementation (log4j, logback etc)
java.sql.Driver interface form a bridge pattern.
class JDBC
DriverManager «interface»
Driver
+ getConnection() «bridge»
+ connect()
oracle.jdbc.driver.OracleDriver
com.mysql.jdbc.Driver
+ connect()
+ connect()
given map object.
Structural Design Patterns
Design Patterns in Java
• We use decorator when we want to add small behaviour on top of existing object.
• A decorator has same interface as the object it decorates or contains.
• Decorators allow you to dynamically construct behaviour by using composition. A decorator can wrap
another decorator which in turn wraps original object.
• Client of object is unaware of existence of decorator.
class Decorator
Component
+ operation(): void
-comp
ConcreteComponent Decorator operation
comp.operation()
+ operation(): void + operation(): void addedBehavior()
# addedBehavior(): void
Concrete Component
Client
• For example the java.io.BufferedOutputStream class decorates any java.io.OutputStream object and adds buffering to file writing
operation. This improves the disk i/o performance by reducing number of writes.
class java_io
«abstract_component»
OutputStream
«concrete_component» «decorator»
FileOutputStream FilterOutputStream
«decorator»
BufferedOutputStream
Composite
Structural Design Patterns
Design Patterns in Java
• We have a parent‐child or whole‐part relation between objects. We can use composite pattern to
simplify dealing with such object arrangements.
• Goal of composite pattern is to simplify the client code by allowing it to treat the composites and leaf
nodes in same way.
• Composites will delegate the operations to its children while leaf nodes implement the functionality.
• You have to decide which methods the base component will define. Adding all methods here will allow
client to treat all nodes same. But it may force classes to implement behaviour which they don’t have.
class Composite
Component
Client
«use»
+ operation(): void
+ add(Component): void
+ remove(Component): void
Leaf Composite
Leaf Node
nodes.
class JSF
«interface»
UIComponent
UIComponentBase
+ getChildren()
+ getChildCount()
Structural Design Patterns
Design Patterns in Java
• We use façade when using our subsystem requires dealing with lots of classes & interfaces
for client. Using façade we provide a simple interface which provides same functionality.
• Façade is not a simple method forwarding but façade methods encapsulate the subsystem
class interactions which otherwise would have been done by client code.
• Facades are often added over existing legacy codes to simplify code usage & reduce coupling
of client code to legacy code.
Facade
+ operation(): void
Subsystem
Package3
Package1
Package2
Class5
Class2 Class3
+ op3(): void
+ op1(): void Class1 Class4
+ op2(): void
• This class takes care of dealing with multiple classes from the java.net package as well as some internal sun packages.
class URL
Client
java.net
URL.class
«facade»
URLStreamHandler
URL
+ openStream()
URLStreamHandlerFactory
+ createURLStreamHandler()
sun.net.www.protocol
Structural Design Patterns
Design Patterns in Java
• We use flyweight design pattern if we need large number of objects of class where we can
easily separate out state that can be shared and state that can be externalized.
• Flyweights store only “intrinsic” state or state that can be shared in any context.
• Code using flyweight instance provides the extrinsic state when calling methods on flyweight.
Flyweight object then uses this state along with its inner state to carry out the work.
• Client code can store extrinsic per flyweight instance it uses or compute it on the fly.
class Flyweight
FlyweightFactory Flyweight
+ getFlyweight(key): Flyweight + operation(extrinsicState): void
ConcreteFlyweight UnsharedConcreteFlyweight
Client - intrinsicState - allState
«use»
+ operation(extrinsicState): void + operation(extrinsicState): void
«use»
Concrete Flyweight
static method serves as the factory method.
• String pool which is maintained by JVM is also an example of flyweight. We can call the intern() method
on a String object to explicitly request this String object to be interned. This method will returned a
reference to already cached object if present or else will create new String in cache if not present.
Note:‐ String.intern() is a native method.
Structural Design Patterns
Design Patterns in Java
pattern.
• Proxy implements same interface as expected of real object. It delegates actual functionality to real object. Proxies are
either given real object or they create one when needed. Some proxies talk to remote service behind the scene.
• Main usage of proxies is for:
• Protection Proxy ‐ Control access to original object’s operations
• Remote Proxy – Provides a local representation of a remote object.
• Virtual proxy – Delays construction of original object until absolutely necessary
• In java we can also use dynamic proxies. These are created on the fly at runtime.
class Proxy
«interface»
Subject
Client + operation(): void
RealSubject Proxy
+ operation(): void + operation(): void
Concrete Subject
Client
• Hibernate uses a proxy to load collections of value types. If you have a relationship in entity class mapped as a
collection, marked as candidate for lazy loading then Hibernate will provide a virtual proxy in its place.
• Spring uses proxy pattern to provide support for features like transactions, caching and general AOP support.
• Hibernate & spring both can create proxies for classes which do not implement any interface. They use third party
frameworks like cglib, aspectJ to create dynamic proxies (remember, Java’s dynamic proxy needs interface) at
runtime.
Behavioral Design Patterns
Design Patterns in Java
chain of responsibility.
• We want this decoupling because we want to give multiple objects chance to handle the request & we
don’t know all objects before hand.
• A handler checks if it can handle the request. If it can’t then it’ll pass the request on to next handler in
chain.
• You can pass the request down the chain even if a handler handles the request. Design pattern
doesn’t prevent that from happening.
+successor
Handler
Client
+ handleRequest(): void
«use»
ConcreteHandlerA ConcreteHandlerB
+ handleRequest(): void + handleRequest(): void
Concrete Handler
Setup chain of responsibility
incoming request and passes it down the chain once its work is done.
i.e. chain.doFilter(request, response);
• In servlet filters, it’s common practice to allow other filters to handle request even if current filter takes
some action on the request.
Behavioral Design Patterns
Design Patterns in Java
• Command pattern allows you to treat requests for operations as objects. This allows you to send these
objects to different parts of code for later execution or to a different thread.
• Commands typically invoke the actual operation on a receiver but contain parameters or information
needed for invocation.
• Client code is responsible for creating instances of command & providing it with receiver and request
information.
• Commands can also implement an undo feature. Here command itself stores a snapshot of receiver.
Client «abstract»
Invoker
Command
+ execute(): void
Receiver
ConcreteCommand
+ operation(): void
- state
+ execute(): void
Receiver
• We create the object of class implementing runnable, providing all information it needs.
• In the run method we’ll call an operation on the receiver.
• We can send this object for later execution to other parts of our application.
• The Action class in struts framework is also an example of Command pattern. Here each URL is mapped to
a action class. We also configure the exact no‐arg method in that class which is called to process that
request.
Behavioral Design Patterns
Design Patterns in Java
• When we want to parse a language with rules we can use the interpreter pattern.
• Each rule in the language becomes an expression class in the interpreter pattern. A terminal
expression provides implementation of interpret method. A non‐terminal expression holds other
expressions and calls interpret on its children.
• This pattern doesn’t provide any solution for actual parsing and building of the abstract syntax tree.
We have to do it outside this pattern.
Context
AbstractExpression
Client
+ interpret(context)
TermialExpression NonTerminalExpression
+ interpret(context) + interpret(context)
Terminal Expression
• Pattern instance is created with an internal abstract syntax tree, representing the grammar rules, during the static
method call compile(). After that we check a sentence against this grammar using Matcher.
• Classes supporting the Unified Expression Language (EL) in JSP 2.1 JSF 1.2. These classes are in javax.el package. We
have javax.el.Expression as a base class for value or method based expressions. We have javax.el.ExpressionFactory
implementations to create the expressions. javax.el.ELResolver and its child classes complete the interpreter
implementation.
Behavioral Design Patterns
Design Patterns in Java
• When we want to decouple a group of objects which communicate with each other then we
can use the mediator design pattern.
• Each object only knows about the mediator object and notifies it about change in it’s state.
Mediator in turn will notify other objects on its behalf.
• Mediators are typically specific to a collaboration. It’s difficult to write a reusable mediator.
Observer design pattern solves this problem. However mediators are easy to implement and
extend.
class Mediator
ConcreteMediator
ConcreteColleagureA
+ collegueChanged(collegue) ConcreteColleagueB
+ setAValue(val)
+ setBValue(val)
Colleague
• Purpose of front controller is to act as a central point where requests from outside world can land and then they are forwarded to
appropriate page controller, often by use of some form of URL to class mapping.
• Front controller pattern can be thought of as a specialized version of mediator pattern. Front controller satisfies mediator characteristics like
acting as central hub for communication between objects. It is specialized since it also handles requests from outside system & performs
lookup to find a specific controller which will handle the request. In mediator when one object changes all others are notified!
Behavioral Design Patterns
Design Patterns in Java
design pattern.
• Iterator needs access to internal data structure of aggregator to provide its functionality. This usually
means it’s quite common to have iterator implemented as inner class.
• Iterator allows the client code to check whether there is an element available to consume and give
next available element.
• We can also provide reverse, or bi‐directional (forward + backward) iterator depending on underlying
data structure.
class Iterator
Aggregate
Client Iterator
+ createIterator()
+ next()
+ hasNext()
ConcreteAggregate ConcreteIterator
+ createIterator() + next()
+ hasNext()
Aggregate
Client
iterators are typically inner classes in each collection class implementing java.util.Iterator interface.
and allows to iterate over a stream.
• The javax.xml.stream.XMLEventReader class is also an iterator. This class turns the XML into a stream of
event objects.
Behavioral Design Patterns
Design Patterns in Java
object to that particular state.
• Memento itself is created such that it doesn’t expose any state stored in it to any other class aside from the
originator.
• Originator provides a method to get a memento out of it. And another method to assign it a memento,
which results in getting the originator’s state reset to the one in memento.
• Mementos need to be saved for them to be of any use. Originator can save them but it adds complexity.
• Memento works well with command pattern. Each commands saves a memento as part of execution.
class Memento
Originator Memento
- state - state CareTaker
+ setMemento(memento) - getState()
+ createMemento() - setState(state)
• The javax.swing.undo.UndoManager acts as the caretaker & implementations of javax.swing.undo.UndoableEdit
interface work as mementos. The javax.swing.text.Document implementation which is model for text components in
swing is the originator.
• The java.io.Serializable is often given as an example of Memento but it is NOT a memento & not even a design pattern.
Memento object itself can be serialized but it is NOT mandatory requirement of the pattern. In fact mementos work
most of the times with in‐memory snapshots of state.
Behavioral Design Patterns
Design Patterns in Java
In‐A‐Hurry Summary
• Observer pattern allows to define one‐to‐many dependency between objects where many objects are interested in state
change of a object.
• Observers register themselves with the subject which then notifies all registered observers if any state change occurs.
• In the notification sent to observers it is common to only send reference of subject instead of state values. Observers will
call the subject back for more information if needed.
• We can also register observers for a specific event only, resulting in improved performance of sending notifications in the
subject.
• This design pattern is also known as publisher‐subscriber pattern. Java messaging uses this pattern but instead of registering
with subject, listeners register with a JMS broker, which acts as a middleman.
In‐A‐Hurry Summary
class Observer
«interface» «interface»
Subject Observer
+ attach(observer) + updated(subject)
+ detach(observer)
+ notify()
ConcreteSubject
- state1 ConcreteObserver
- state2
+ updated(subject)
+ attach(observer)
+ detach(observer)
+ notify()
+ getState(name)
In-A-Hurry Summary
Subject Observer
Concrete Observer
• Another commonly used example is various listeners in Java Servlet application. We can create various listeners
by implementing interfaces like HttpSessionListener, ServletRequestListener.
certain events occur like, creation of a request or addition of a value to the session.
• The notification will sent to observers based on the event that has taken place and the interface(s)
implemented by registered observers.
• Spring also supports Observer through the org.springframework.context.ApplicationListener interface.
Behavioral Design Patterns
Design Patterns in Java
object we can use the state pattern.
• Our main object (aka context) delegates the actual operation to its current state. States will implement
behavior which is specific to a particular state value.
• Context object’s state change is explicit now, since we change the entire state object.
• State transitions are handled either by states themselves or context can trigger them.
• We can reuse state objects if they don’t have any instance variables and only provide behavior.
ConcreteStateA ConcreteStateB
+ handleOperation() + handleOperation()
Concrete State
• JSF has six phases: RestoreViewPhase, ApplyRequestValues, ProcessValidationsPhase,
UpdateModelValuesPhase, InvokeApplicationPhase, and RenderResponsePhase
• In case you are not familiar with JSF, then you can always fall back on the order processing example that
we studied.
Behavioral Design Patterns
Design Patterns in Java
(called context) can now be configured with desired implementation of an algorithm.
• It is typically the responsibility of client code which is using our context object to configure it.
• Strategy objects are given all data they need by the context object. We can pass data either in form of
arguments or pass on context object itself.
• Strategy objects typically end up being stateless making them great candidates for flyweight pattern.
• Client code ends up knowing about all implementations of strategy since it has to create their objects.
class Strategy
Context «interface»
-strategy Strategy
+ operation(): void
+ runAlgorithm(): void
ConcreteStrategyA ConcreteStrategyB
+ runAlgorithm(): void + runAlgorithm(): void
Context
Concrete Strategy
of comparator, each using a different algorithm to perform comparison and supply those to various sort
methods.
• Another example of strategy pattern is the ImplicitNamingStrategy & PhysicalNamingStrategy contracts in
Hibernate. Implementations of these classes are used when mapping an Entity to database tables. These
classes tell hibernate which table to use & which columns to use.
• We can use different algorithms to perform mapping from domain model mapping to a logical name via
ImplicitNamingStrategy & then from logical name to physical name via PhysicalNamingStrategy.
Behavioral Design Patterns
Design Patterns in Java
defined as abstract methods in base class.
• Subclasses of our abstract class will provide implementation of steps. This way we can have different
implementations for same algorithm.
• Client will create object of any of the concrete subclasses and use the algorithm.
• Factory method design pattern is often implemented as part of template method design pattern.
• One drawback of template method is algorithm implementation is now spread across multiple classes so
it makes it slightly difficult to understand.
class TemplateMethod
AbstractClass
+ templateMethod()
+ step1()
+ step2()
+ step3()
ConcreteClassA
ConcreteClassB
+ step1()
+ step2() + step1()
+ step3() + step2()
+ step3()
exampels of template method pattern.
Behavioral Design Patterns
Design Patterns in Java
objects.
• Visitors define class specific methods which work with an object of that class to provide new functionality.
• To use this pattern classes define a simple accept method which gets a reference to a visitor and inside this
method, objects class method on visitor which is defined for that specific class.
• Adding a new functionality means creating a new visitor and implementing new functionality in that class
instead of modifying each class where this functionality is needed.
• This pattern is often used where we have an object structure and then another class or visitor itself iterates
over this structure passing our visitor object to each object.
«interface»
Visitor
Client
+ visitConcreteElementA(concreteElementA)
+ visitConcreteElementB(concreteElementB)
ConcreteVisitorB
ConcreteVisitorA
+ visitConcreteElementA(concreteElementA)
+ visitConcreteElementA(concreteElementA) + visitConcreteElementB(concreteElementB)
+ visitConcreteElementB(concreteElementB)
Role:- Element
- Defines accept operation
«interface»
ObjectStructure Element
+ accept(visitor)
ConcreteElementA ConcreteElementB
+ accept(visitor) + accept(visitor)
+ operationA() + operationB()
Abstract Element
• Another example of visitor pattern is the java.nio.file.FileVisitor & its implementation SimpleFileVisitor.
Behavioral Design Patterns
Design Patterns in Java
• Method implementations in a Null object will not do anything. In case a return value is expected, these
methods will return a sensible, hard‐coded default value.
• Classes which use Null object won’t be aware of presence of this special implementation. Whole purpose
of the pattern is to avoid null checks in other classes.
• Null objects do not transform into real objects, nor do they use indirection to real objects.
class NullObject
AbstractClass
Client
«use» + operation(): void
ConcreteClass NullClass
+ operation(): void + operation(): void operation
//do nothing
they are not the examples of this pattern is that they are abstract classes but without any abstract method.