Strategy Pattern

Design Aspect

An algorithm

  • Define a family of algorithms, encapsulate each one, and make them interchangeable.
  • Strategy lets the algorithm vary independently from clients that use it.

Problem

  • Multiple classes will be modified if new behaviors are to be added.
  • All duplicate code will be modified if the behavior is to be changed.

Graph

Steps

Step 1.

1
2
3
4
// Strategy.java
public interface Strategy{
public int doOperation(int num1, int num2);
}

Step 2.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// OperationAdd.java
public class OperationAdd implements Strategy{
@Override
public int doOperation(int num1, int num2){
return num1 + num2;
}
}
// OperationSubtract.java
public class OperationSubtract implements Strategy{
@Override
public int doOperation(int num1, int num2){
return num1 - num2;
}
}
// OperationMultiply.java
public class OperationMultiply implements Strategy{
@Override
public int doOperation(int num1, int num2){
return num1 * num2;
}
}

Step 3.

1
2
3
4
5
6
7
8
9
10
11
12
// Context.java
public class Context{
private Strategy strategy;
public Context(Strategy strategy){
this.strategy = strategy;
}
public int executeStrategy(int num1, int num2){
return strategy.doOperation(num1, num2);
}
}

Step 4.

1
2
3
4
5
6
7
8
9
10
11
12
13
// StrategyPatternDemo.java
public class StrategyPatternDemo{
public static void main(String[] args){
Context context = new Context(new OperationAdd());
System.out.println("10 + 5 = " + context.executeStrategy(10, 5));
context = new Context(new OperationSubtract());
System.out.println("10 - 5 = " + context.executeStrategy(10, 5));
context = new Context(new OperationMultiply());
System.out.println("10 * 5 = " + context.executeStrategy(10, 5));
}
}

Example Statement

  • In a duck Game,
    • There are four types of ducks in the game: MallardDuck, RedheadDuck, RubberDuck, and DecoyDuck.
    • All types of the ducks have the same swim behavior but are with different displays.
    • Some ducks can fly with wings, but some cannot fly.
    • A duck can quack, squeak, or be silent.

Observer Pattern

Design Aspect

Number of objects that depend on another object; how the dependent objects stay up to date

  • Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

Problem

  • The code will be modified if a new display/presentation is going to be added.

Graph

Steps

Step 1.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// Subject.java
import java.util.ArrayList;
import java.util.List;
public class Subject {
private List<Observer> observers = new ArrayList<Observer>();
private int state;
public int getState(){
return state;
}
public void setState(int state){
this.state = state;
notifyAllObservers();
}
public void attach(Observer observer){
observers.add(observer);
}
public void notifyAllObservers(){
for (Observer observer : observers){
observer.update();
}
}
}

Step 2.

1
2
3
4
5
// Observer.java
public abstract class Observer {
protected Subject subject;
public abstract void update();
}

Step 3.

1
2
3
4
5
6
7
8
9
10
11
12
// BinaryObserver.java
public class BinaryObserver extends Observer {
public BinaryObserver(Subject subject){
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println("Binary String: " + Integer.toBinaryString(subject.getState()));
}
}

1
2
3
4
5
6
7
8
9
10
11
12
// OctalObserver.java
public class OctalObserver extends Observer {
public OctalObserver(Subject subject){
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println("Octal String: " + Integer.toOctalString(subject.getState()));
}
}
1
2
3
4
5
6
7
8
9
10
11
12
// HexaObserver.java
public class HexaObserver extends Observer {
public HexaObserver(Subject subject){
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println("Hex String: " + Integer.toHexString(subject.getState()));
}
}

Step 4.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// ObserverPatternDemo.java
public class ObserverPatternDemo{
public static void main(String[] args){
Subject subject = new Subject();
new HexaObserver(subject);
new OctalObserver(subject);
new BinaryObserver(subject);
System.out.println("First state change: 15");
subject.setState(15);
System.out.println("Second state change: 10");
subject.setState(10);
}
}

Example Statement

  • In a spreadsheet application,
    • A spreadsheet object, bar chart object, and pie chart object can depict information in the same application data object by using different presentations.
    • When the user changes the information in the spreadsheet, the bar chart reflects the changes immediately, and vice versa.
    • Both a spreadsheet object and bar chart object can depict information in the same application data object by using different presentations.

Decorator Pattern

Design Aspect

Responsibilities of an object without subclassing

  • Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.

Problem

  • A class will be modified if you want to attach additional responsibilities(decorators) to an object dynamically.
  • One way to add responsibilities is with inheritance.
  • A client is difficult to control how and when to decorate the component with a object.

Graph

Steps

Step 1.

1
2
3
4
// Shape.java
public interface Shape{
void draw();
}

Step 2.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Rectangle.java
public class Rectangle implement Shape {
@Override
public void draw(){
System.out.println("Shape: Rectangle");
}
}
// Circle.java
public class Circle implement Shape{
@Override
public void draw(){
System.out.println("Shape: Circle");
}
}

Step 3.

1
2
3
4
5
6
7
8
9
10
11
12
// ShapeDecorator.java
public abstract class ShapeDecorator implements Shape{
protected Shape decoratedShape;
public ShapeDecorator(Shape decoratedShape){
this decoratedShape = decoratedShape;
}
public void draw(){
decoratedShape.draw();
}
}

Step 4.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// RedShapeDecorator.java
public class RedShapeDecorator extends ShapeDecorator{
public RedShapeDecorator(Shape decoratedShape){
super(decoratedShape);
}
@Override
public void draw(){
decoratedShape.draw();
setRedBorder(decoratedShape);
}
private void setRedBorder(Shape decoratedShape){
System.out.println("Border Color: Red");
}
}

Step 5.

1
2
3
4
5
6
7
8
9
10
11
12
// DecoratorPatternDemo.java
public class DecoratorPatternDemo{
public static void main(String[] args){
Shape circle = new Circle();
Shape redCircle = new RedShapeDecorator(new Circle());
Shape redRectangle = new RedShapeDecorator(new Rectangle());
System.out.println("\nCircle of red border");
redCircle.draw();
System.out.println("\nRectangle of red border");
redRectangle.draw();
}
}

Example Statement

  • In FileViewer,
    • We have a TextView object that displays text in a window.
    • TextView has no scroll bars by default, because we might not always need them.
    • We can also add a thick black border around the TextView.
    • It is highly likely that we will support various file formats for display in the future.
  • Starbuzz Coffee,
    • Starbuzz Coffee shops are scrambling to update their ordering systems to match their beverage offerings (e.g. HouseBlend, DarkRoast, Decaf and Espresso) to summate how they cost.
    • In addition to your coffee, you can also ask for several condiments like steamed milk, soy, and mocha, and have these, so they really need to get them built into their order system

Factory Method Pattern

Design Aspect

Subclass of object that is instantiated

  • Define an interface for creating an object, but let subclasses decide which class to instantiate. Facotry Method lets a class defer instantiation to subclasses.

Problem

  • As the objects being created changes over time, we need to modify the code of the creator object for the creations over and over again.

Graph

Steps

Step 1.

1
2
3
4
// Shape.java
public interface Shape{
void draw();
}

Step 2.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Rectangle.java
public class Rectangle implements Shape{
@Override
public void draw(){
System.out.println("Inside Rectangle::draw() method.");
}
}
// Circle.java
public class Circle implements Shape{
@Override
public void draw(){
System.out.println("Inside Circle::draw() method.");
}
}
// Square.java
public class Square implements Shape{
@Override
public void draw(){
System.out.println("Inside Square::draw() method.");
}
}

Step 3.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// ShapeFactory.java
public abstract class ShapeFactory{
public abstract Shape getShape();
}
// CircleFactory.java
public class CircleFactory extends ShapeFactory{
public Shape getShape(){
return new Circle();
}
}
// RectangleFactory.java
public class RectangleFactory extends ShapeFactory{
public Shape getShape(){
return new Rectangle();
}
}
// SquareFactory.java
public class SquareFactory extends ShapeFactory{
public Shape getShape(){
return new Square();
}
}

Step 4.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// FactoryPatternDemo.java
public class FactoryPatternDemo {
public static void main(String[] args){
ShapeFactory circleFactory = new CircleFactory();
ShapeFactory rectangleFactory = new RectangleFactory();
ShapeFactory squareFactory = new SquareFactory();
Shape circle = circleFactory.getShape();
Shape rectangle = rectangleFactory.getShape();
Shape square = squareFactory.getShape();
circle.draw();
rectangle.draw();
square.draw();
}
}

Example Statement

  • Powerful Document Viewer,
    • A powerful application can present multiple documents at the same time.
    • These documents include DrawingDocument, TextDocument, and so on.
    • The application is responsible for managing documents and will create them as required.
  • Pizza Store,
    • The store makes more than one type of pizza: Cheese Pizza, Greek Pizza, and Pepperoni Pizza
    • Each pizza has different way to prepare, and has the same way to bake, to cut, and to box.
    • To make this store more competitive, you may add a new flavor of pizza or remove unpopular ones.

Abstract Factory Pattern

Design Aspect

Families of product objects

  • Provide an interface for creating families of related or dependent objects without specifying their concrete classes.

Problem

  • As the families of related or dependent objects are added, we need to write new object classes for the new families.

Graph

Steps

Step 1.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Window.java
public interface Window{
void build();
}
// Scrollbar.java
public interface Scrollbar{
void build();
}
// Button.java
public interface Button{
void build();
}

Step 2.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// MotifWindow.java
public class MotifWindow implements Window{
@Override
public void build(){
System.out.println("Inside MotifWindow::build() method.")
}
}
// PMWindow.java
public class PMWindow implements Window{
@Override
public void build(){
System.out.println("Inside PMWindow::build() method.")
}
}
// MotifScrollbar.java
public class MotifScrollbar implements Scrollbar{
@Override
public void build(){
System.out.println("Inside MotifScrollbar::build() method.")
}
}
// PMScrollbar.java
public class PMScrollbar implements Scrollbar{
@Override
public void build(){
System.out.println("Inside PMScrollbar::buildl() method.")
}
}
// MotifButton.java
public class MotifButton implements Button{
@Override
public void build(){
System.out.println("Inside MotifButton::build() method.")
}
}
// PMButton.java
public class PMButton implements Button{
@Override
public void build(){
System.out.println("Inside PMButton::build() method.")
}
}

Step 3.

1
2
3
4
5
6
// WidgetFactory.java
public interface WidgetFactory{
public Window createWindow();
public Scrollbar createScrollbar();
public Button createButton();
}

Step 4.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// MotifWidgetFactory.java
public class MotifWidgetFactory implements WidgetFactory{
public Window createWindow(){
return new MotifWindow();
}
public Scrollbar createScrollbar(){
return new MotifScrollbar();
}
public Button createButton(){
return new MotifButton();
}
}
// PMWidgetFactory.java
public class PMWidgetFactory implements WidgetFactory{
public Window createWindow(){
return new PMWindow();
}
public Scrollbar createScrollbar(){
return new PMScrollbar();
}
public Button createButton(){
return new PMButton();
}
}

Step 5.

1
2
3
4
5
6
7
8
9
10
11
12
13
// GUIApplication.java
public class GUIApplication{
public static void main(String[] args){
WidgetFactory motifWidgetFactory = new MotifWidgetFactory();
WidgetFactory pmWidgetFactory = new PMWidgetFactory();
motifWidgetFactory.createWindow().build();
motifWidgetFactory.createScrollbar().build();
motifWidgetFactory.createButton().build();
pmWidgetFactory.createWindow().build();
pmWidgetFactory.createScrollbar().build();
pmWidgetFactory.createButton().build();
}
}

Example Statement

  • A GUI Application with Multiple Styles
    • A GUI Application consists of some kinds of widgets like window, scroll bar, and button.
    • Each widget in the GUI application has two or more implementations according to different lookand-feel standards, such as Motif and Presentation Manager.
    • The GUI application can switch its look-and-feel style from one to another.
  • Pizza Store
    • In a pizza store system, two flavors of pizza are offered: Cheese Pizza and Pepperoni Pizza.
    • Each flavor of pizza can be categorized into two styles: New York Style and Chicago Style.
    • Different pizza style needs different dough and sauce:
    • NY Style: Thin Crust Dough, Marinara Sauce
    • Chicago Style: Thick Crust Dough, Plum Tomato Sauce

Iterator Pattern

Design Aspect

How an aggregate’s elements are accessed, traversed

  • Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.

Problem

  • The method of accessing the elements of two aggregate objects with different representations will be modified if a new aggregate object with different representation is added.

Graph

Steps

Step 1.

1
2
3
4
5
6
7
8
9
10
// Iterator.java
public interface Iterator{
public boolean hasNext();
public Object next();
}
// Container.java
public interface Container{
public Iterator getIterator();
}

Step 2.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// NameRepository.java
public class NameRepository implements Container{
public String name[] = {"Robert", "John", "Julie", "Lora"};
@Override
public Iterator getIterator(){
return new NameIterator();
}
private class NameIterator implements Iterator{
int index;
@Override
public boolean hasNext(){
if (index < names.length){
return true;
}
return false;
}
@Override
public Object next(){
if (this.hasNext()){
return names[index++];
}
return null;
}
}
}

Step 3.

1
2
3
4
5
6
7
8
9
10
// IteratorPatternDemo.java
public class IteratorPatternDemo{
public static void main(String[] args){
NameRepository nameRepository = new NameRepository();
for (Iterator iter = nameRepository.getIterator(); iter.hasNext();){
String name = (String)iter.next();
System.out.println("Name : " + name);
}
}
}

Example Statement

  • Print Out Items in Different Data Structures,
    • A List data structure is implemented with a String array which can contain a series of String objects.
    • We can access List by calling the get() method with an index, and know how many Strings inside the List with a public attribute: length.
    • Furthermore, another data structure called SkipList which consists of a series of SkipNodes.
    • Each SkipNode can be accessed by invoking the getNode() method in SkipList with an index. And we have the idea about the size of SkipList with its size() method.
    • Now we have to traverse both List and SkipList to print out those object items in the two different data structures for some purpose.
  • Merge Tow Menus
    • A waitress of Pancake House keeps a breakfast menu which uses an ArrayList to hold its menu items.
    • And a waitress of Diner keeps a lunch menu which uses an Array to hold its menu items.
    • Now, these two restaurants are merged and tend to provide service in one place, so a waitress should keep both menus on hand.
    • How to the waitress print two different menu representations at a time?

Composite Pattern

Design Aspect

Structure and composition of an object

  • Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.

Problem

  • The user can group components to form larger components, which in turn can be grouped to form still larger components.

Graph

Steps

Step 1.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// Employee.java
import java.util.ArrayList;
import java.util.List;
public class Employee{
private String name;
private String dept;
private int salary;
private List<Employee> subordinates;
public Employee(String name, String dept, int sal){
this.name = name;
this.dept = dept;
this.salary = sal;
subordinates = new ArrayList<Employee>();
}
public void add(Employee e){
subordinates.add(e);
}
public void remove(Employee e){
subordinates.remove(e);
}
public List<Employee> getSubordinates(){
return subordinates;
}
public String toString(){
return ("Employee : [Name : " + name + ", dept : " + dept + ", salary : " + salary + " ]");
}
}

Step 2.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// CompositePatternDemo.java
public class CompositePatternDemo{
public static void main(String[] args){
Employee CEO = new Employee("John", "CEO", 30000);
Employee headSales = new Employee("Robert", "Head Sales", 20000);
Employee headMarketing = new Employee("Micheal", "Head Marketing", 20000);
Employee clerk1 = new Employee("Laura", "Marketing", 10000);
Employee clerk2 = new Employee("Bob", "Marketing", 10000);
Employee salesExcutive1 = new Employee("Richard", "Sales", 10000);
Employee salesExcutive2 = new Employee("Rob", "Sales", 10000);
CEO.add(headSales);
CEO.add(headMarketing);
headSales.add(salesExcutive1);
headSales.add(salesExcutive2);
headMarketing.add(clerk1);
headMarketing.add(clerk2);
System.out.println(CEO);
for (Employee headEmployee : CEO.getSubordinates()){
System.out.println(headEmployee);
for (Employee employee : headEmployee.getSubordinates()){
System.out.println(employee);
}
}
}
}

Example Statement

  • In schematic capture application,
    • There are some basic components can be drawn such as Text, Line, and Rectangle.
    • The user can group basic components to form larger components, which in turn can be grouped to form still larger components.
  • Merge two menus extends,
    • A dessert submenu is going to be added to the Diner menu.

Facade Pattern

Design Aspect

Interface to a subsystem

  • Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.

Problem

  • A common design goal is to minimize the communication and dependencies between subsystems.

Graph

Steps

Step 1.

1
2
3
4
// Shape.java
public interface Shape{
void draw();
}

Step 2.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Rectangle.java
pulic class Rectangle implements Shape{
@Override
public void draw(){
System.out.println("Rectangle::draw()");
}
}
// Circle.java
pulic class Circle implements Shape{
@Override
public void draw(){
System.out.println("Circle::draw()");
}
}
// Square.java
pulic class Square implements Shape{
@Override
public void draw(){
System.out.println("Square::draw()");
}
}

Step 3.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// ShapeMaker.java
public class ShapeMaker{
private Shape circle;
private Shape rectangle;
private Shape square;
public ShapeMaker(){
circle = new Circle();
rectangle = new Rectangle();
square = new Square();
}
public void drawCircle(){
circle.draw();
}
public void drawRectangle(){
rectangle.draw();
}
public void drawSquare(){
square.draw();
}
}

Step 4.

1
2
3
4
5
6
7
8
9
// FacadePatternDemo.java
public class FacadePatternDemo{
public static void main(String[] args){
ShapeMaker shapeMaker = new ShapeMaker();
shapeMaker.drawCircle();
shapeMaker.drawRectangle();
shapeMakder.drawSquare();
}
}

Example Statement

  • A Programming Environment
    • A compiler subsystem contains classes such as Scanner, Parser, ProgramNode, and BytecodeStream.
    • The client classes need to use Scanner, Parser, ProgramNode, and BytecodeStream to compile some code.
  • Home Sweet Home Theater
    • A Home Theater consists of an amplifier, a DVD player, a projector, a screen, a popcorn popper, and theater lights.
    • A user can watch a movie through the following process:
    • Turn on the popcorn popper
    • Start the popper popping
    • Dim the lights
    • Put the screen down
    • Turn the projector on
    • Turn the sound amplifier on
    • Turn the DVD player on
    • Start the DVD player playing

Template Method Pattern

Design Aspect

Steps of an algorithm

  • Define the skeleton of an algorithm in an operation, deferring some steps to subclasses.
  • Templete Method lets subclasses redefine certain steps of an algorithm without changing the algorithm’s structure.

Problem

  • Two classes with code duplications would be modified at the same time if the duplicate code is being changed.

Graph

Steps

Step 1.

1
2
3
4
5
6
7
8
9
10
11
12
// Game.java
public abstract class Game{
abstract void initialize();
abstract void statePlay();
abstract void endPlay();
public final void play(){
initialize();
startPlay();
endPlay();
}
}

Step 2.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// Cricket.java
public class Cricket extends Game{
@Override
void endPlay(){
System.out.println("Cricket Game Finished!");
}
@Override
void initialize(){
System.out.println("Cricket Game Inisialized!");
}
@Override
void startPlay(){
System.out.println("Cricket Game Start!");
}
}
// Football.java
public class Football extends Game{
@Override
void endPlay(){
System.out.println("Football Game Finished!");
}
@Override
void initialize(){
System.out.println("Football Game Inisialized!");
}
@Override
void startPlay(){
System.out.println("Football Game Start!");
}
}

Step 3.

1
2
3
4
5
6
7
8
9
10
// TemplatePatternDemo.java
public class TemplatePatternDemo{
public static void main(String[] args){
Game game = new Cricket();
game.play();
System.out.println();
game = new Football();
game.play();
}
}

Example Statement

  • Opening Documents in Applications
    • In order to open a text document, a text application
    • will:
    • Check if the text document can be opened
    • Create a text document object and hold a reference of the text document object.
    • Add the text document object to the Application.
    • Read text document.
    • Opening Documents in Applications
    • There is another new requirement.
    • Opening a spreadsheet document with a spreadsheet application carries the same steps in the algorithm(process) as the text document.
    • Check if the spreadsheet document can be opened.
    • Create a spreadsheet document object and hold a reference of the spreadsheet document object.
    • Add the spreadsheet document object to the Application.
    • Read spreadsheet document.
    • Prepare Caffeine Beverages
    • Please follow these recipes precisely when preparing Starbuzz beverages
    • Starbuzz Coffee Recipe
    • Boil some water
    • Brew coffee in boiling water
    • Pour Coffee in cup
    • Add sugar and milk
    • Starbuzz Tea Recipe
    • Boil some water
    • Steep tea in boiling water
    • Pour tea in cup
    • Add lemon

Command Pattern

Design Aspect

When and how a request is fulfilled

  • Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.

Problem

  • The invoker object is subject to be modified once the set of the actions on a receiver is changed.

Graph

Steps

Step 1.

1
2
3
4
// Order.java
public interface Order{
void execute();
}

Step 2.

1
2
3
4
5
6
7
8
9
10
11
12
13
// Stock.java
public class Stock{
private String name = "ABC";
private int quantity = 10;
public void buy(){
System.out.println("Stock [ Name: " + name + ", Quantity: " + quantity + " ] bought");
}
public void sell(){
System.out.println("Stock [ Name: " + name + "Quantity: " + quantity + " ] sold");
}
}

Step 3.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// BuyStock.java
public class BuyStockOrder implements Order{
private Stock abcStock;
public BuyStockOrder(Stock abcStock){
this.abcStock = abcStock;
}
public void execute(){
abcstock.buy();
}
}
// SellStock.java
public class SellStockOrder implements Order{
private Stock abcStock;
public SellStockOrder(Stock abcStock){
this.abcStock = abcStock;
}
public void execute(){
abcStock.sell();
}
}

Step 4.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Broker.java
import java.util.ArrayList;
import java.util.List;
public class Broker{
private List<Order> orderList = new ArrayList<Order>();
public void takeOrder(Order order){
orderList.add(order);
}
public void placeOrders(){
for (Order order : orderList){
order.execute();
}
orderList.clear();
}
}

Step 5.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// CommandPatternDemo.java
public class CommandPatternDemo{
public static void main(String[] args){
Stock abcStock = new Stock();
BuyStockOrder buyStockOrder = new BuyStockOrder(abcStock);
SellStockOrder sellStockOrder = new SellStockOrder(abcStock);
Broker broker = new Broker();
broker.takeOrder(buyStockOrder);
broker.takeOrder(sellStockOrder);
broker.placeOrder();
}
}

Example Statement

  • Remote Control,
    • The remote control can control a stereo remotely.
    • While a stereo is switched on by the remote control, the CD and volume will be set at the same time.
  • Cut, Copy, Paste on a Document,
    • An editor application carries a document.
    • A menu in the editor application contains some menu items which performs three specific operations such as cut, copy, and paste on a document.

Adapter Pattern

Design Aspect

Interface to an object

  • Convert the interface of a class inter another interface clients expect. Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces.

Problem

  • The request method of the requester object should be modified once it changes its receiver class with a new interface.

Graph

Steps

Step 1.

1
2
3
4
5
6
7
8
9
10
// MediaPlayer.java
public interface MediaPlayer{
public void play(String audioType, String fileName);
}
// AdvancedMediaPlayer.java
public interface AdvancedMediaPlayer{
public void playVlc(String fileName);
public void playMp4(String fileName);
}

Step 2.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// VlcPlayer.java
public class VlcPlayer implements AdvancedMediaPlayer{
@Override
public void playVlc(String fileName){
System.out.println("Playing vlc file. Name: " + fileName);
}
@Override
public void playMp4(String fileName){}
}
// Mp4Player.java
public class Mp4Player implements AdvancedMediaPlayer{
@Override
public void playVlc(String fileName){}
@Override
public void playMp4(String fileName){
System.out.println("Playing mp4 file. Name: " + fileName);
}
}

Step 3.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// MediaAdapter.java
public class MediaAdapter implements MediaPlayer{
AdvancedMediaPlayer advancedMusicPlayer;
public MediaAdapter(String audioType){
if (audioType.equalsIgnoreCase("vlc")){
advancedMusicPlayer = new VlcPlayer();
}
else if (audioType.equalsIgnoreCase("mp4")){
advancedMusicPlayer = new Mp4Player();
}
}
@Override
public void play(String audioType, String fileName){
if (audioType.equalsIgnoreCase("vlc")){
advancedMusicPlayer.playVlc(fileName);
}
else if (audioType.equalsIgnoreCase("mp4")){
advancedMusicPlayer.playMp4(fileName);
}
}
}

Step 4.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// AudioPlayer.java
public class AudioPlayer implements MediaPlayer{
MediaAdapter mediaAdapter;
@Override
public void play(String audioType, String fileName){
if(audioType.equalsIgnoreCase("mp3")){
System.out.println("Playing mp3 file. Name: " + fileName);
}
else if(audioType.equalsIgnoreCase("vlc") || audioType.equalsIgnoreCase("mp4")){
mediaAdapter = new MediaAdapter(audioType);
mediaAdapter.play(audioType, fileName);
}
else{
System.out.println("Invalid media. " + audioType + " format not supported");
}
}
}

Step 5.

1
2
3
4
5
6
7
8
9
10
11
// AdapterPatternDemo.java
public class AdapterPatternDemo{
public static void main(String[] args){
AudioPlayer audioPlayer = new AudioPlayer();
audioPlayer.play("mp3", "beyond the horizon.mp3");
audioPlayer.play("mp4", "alone.mp4");
audioPlayer.play("vlc", "far far away.vlc");
audioPlayer.play("avi", "mind me.avi");
}
}

Example Statement

  • New Vendor in Existing Software,
    • You’ve got an existing client class that use a vendor class library.
    • After a while you found another vendor class library is better, but the new vendor designed their interfaces differently.
  • A Text Shape,
    • A drawing editor
    • Want to add a TextShape that using display method to display text and using boundingBox method to get bounding.
    • A drawing editor
    • Meanwhile, an external library already provide a TextView class using display method to display text and using getExtent method to get bounding.
    • We’d like to reuse TextView to display text of shape.

Builder Pattern

Design Aspect

how a composite object gets created

  • Separate the construction of a complex object from its representation so that the same construction process can create different representations.

Problem

  • Construct complex objects step-by-step, and return the product as a final step.

Graph

Steps

Step 1.

1
2
3
4
5
6
7
8
9
10
11
// Item.java
public interface Item{
public String name();
public Packing packing();
public float price();
}
// Packing.java
public interface Packing{
public String pack();
}

Step 2.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Wrapper.java
public class Wrapper implements Packing{
@Override
public String pack(){
return "Wrapper";
}
}
// Bottle.java
public class Bottle implements Packing{
@Override
public String pack(){
return "Bottle";
}
}

Step 3.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Burger.java
public abstract class Burger implements Item{
@Override
public Packing packing(){
return new Wrapper();
}
@Override
public abstract float price();
}
// ColdDrink.java
public abstract class ColdDrink implements Item{
@Override
public Packing packing(){
return new Bottle();
}
@Override
public abstract float price();
}

Step 4.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
// VegBurger.java
public class VegBurger extends Burger{
@Override
public float price(){
return 25.0f;
}
@Override
public String name(){
return "Veg Burger";
}
}
// ChickenBurger.java
public class ChickenBurger extends Burger{
@Override
public float price(){
return 50.5f;
}
@Override
public String name(){
return "Chicken Burger";
}
}
// Coke.java
public class Coke extends ColdDrink{
@Override
public float price(){
return 30.0f;
}
@Override
public String name(){
return "Coke";
}
}
// Pepsi.java
public class Pepsi extends ColdDrink{
@Override
public float price(){
return 35.0f;
}
@Override
public String name(){
return "Pepsi";
}
}

Step 5.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// Meal.java
import java.util.ArrayList;
import java.util.List;
public class Meal{
private List<Item> items = new ArrayList<Item>();
public void addItem(Item item){
items.add(item);
}
public float getCost(){
flaot cost = 0.0f;
for (Item item : items){
cost += item.price();
}
return cost;
}
public void showItems(){
for (Item item : items){
System.out.println("Item : " + item.name());
System.out.println(", Packing : " + item.packing().pack());
System.out.println(", Price : " + item.price());
}
}
}

Step 6.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// MealBuilder.java
public class MealBuilder{
public Meal prepareVegMeal{
Meal meal = new Meal();
meal.addItem(new VegBurger());
meal.addItem(new Coke());
return meal;
}
public Meal prepareNonVegMeal(){
Meal meal = new Meal();
meal.addItem(new ChickenBurger());
meal.addItem(new Pepsi());
return meal;
}
}

Step 7.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// BuilderPatternDemo.java
public class BuilderPatternDemo{
public static void main(String[] args){
MealBuilder mealBuilder = new MealBuilder();
Meal vegMeal = mealBuilder.prepareVegMeal();
System.out.println("Veg Meal");
vegMeal.showItems();
System.out.println("Total Cost: " + vegMeal.getCost());
Meal nonVegMeal = mealBuilder.prepareNonVegMeal();
System.out.println("\nNon-Veg Meal");
nonVegMeal.showItems();
System.out.println("Total Cost: " + nonVegMeal.getCost());
}
}

Example Statement

  • A RTF(Rich Text Fromat) Converter,
    • A reader for the RTF (Rich Text Format) document exchange format should be able to convert RTF to many text formats.
    • The reader converts RTF documents into TeX text or into a text widget by recognizing different RTF tokens(Character, Font Change and Paragraph).
  • A Vacation Planner,
    • Patternsland wants to build a vacation planner.
    • A vacation planner can choose a hotel and various types of admission tickets, make restaurant reservations, even book special events and day. The difference types vacation (normal, backpacking) will have difference options.

State Pattern

Design Aspect

states of an object

  • Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.

Problem

  • An object’s behavior depends on its state, and it must change its behavior at run-time depending on that state.

Graph

Steps

Step 1.

1
2
3
4
// State.java
public interface State{
public void doAction(Context context);
}

Step 2.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// StartState.java
public class StartState implements State{
public void doAction(Context context){
System.out.println("Player is in start state");
context.setState(this);
}
public String toString(){
return "Start State";
}
}
// StopState.java
public class StopState implements State{
public void doAction(Context context){
System.out.println("Player is in stop state");
context.setState(this);
}
public String toString(){
return "Stop State";
}
}

Step 3.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Context.java
public class Context{
private State state;
public Context(){
state = null;
}
public void setState(State state){
this.state = state;
}
public State getState(){
return state;
}
}

Step 4.

1
2
3
4
5
6
7
8
9
10
11
12
13
// StatePatternDemo.java
public class StatePatternDemo{
public static void main(String[] args){
Context context = new Context();
StartState startState = new StartState();
startState.doAction(context);
System.out.println(context.getState().toString());
StopState stopState = new StopState();
stopState.doAction(context);
System.out.println(context.getState().toString());
}
}

Example Statement

  • A TCP Connection,
    • A class TCPConnection that represents a network connection.
    • When a TCPConnection object receives an Open request from other objects, it responds differently depending on its current state. A TCPConnection object can be in one of several different states: Established, Listening, and Closed.
  • A Gumball Machine
    • A GumballMachine has four actions: Insert Quarter, Eject Quarter, Turn Crank, and Dispense.
    • There are four states in the GumballMachine: No Quarter, Has Quarter, Out of Gumballs and Gumball Sold. As the following state diagram.

Visitor Pattern

Design Aspect

Operations that can be applied to objects
without changing their classes

  • Represent an operation to be performed on the elements of an object structure.
  • Visitor lets you define a new operation without changing the classes of the elements on which it operates.

Problem

  • The problem is that distributing all these operations across the various classes in an object structure leads to a system that’s hard to understand, maintain, and change. Moreover, adding a new operation usually requires recompiling all of these classes.

Graph

Steps

Step 1.

1
2
3
4
// ComputerPart.java
public interface ComputerPart{
public void accept(ComputerPartVisitor computerPartVisitor);
}

Step 2.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// Keyboard.java
public class Keyboard implements ComputerPart{
@Override
public void accept(ComputerPartVisitor computerPartVisitor){
computerPartVisitor.visit(this);
}
}
// Monitor.java
public class Monitor implements ComputerPart{
@Override
public void accept(ComputerPartVisitor computerPartVisitor){
computerPartVisitor.visit(this);
}
}
// Mouse.java
public class Mouse implements ComputerPart{
@Override
public void accept(ComputerPartVisitor computerPartVisitor){
computerPartVisitor.visit(this);
}
}
// Computer.java
public class Computer implements ComputerPart{
ComputerPart[] parts;
public Computer(){
parts = new ComputerPart[] {new Mouse(), new Keyboard(), new Monitor()};
}
@Override
public void accept(ComputerPartVisitor computerPartVisitor){
for (int i = 0; i < parts.length; i++){
parts[i].accept(computerPartVisitor);
}
computerPartVisitor.visit(this);
}
}

Step 3.

1
2
3
4
5
6
7
// ComputerPartVisitor.java
public interface ComputerPartVisitor{
public void visit(Computer computer);
public void visit(Mouse mouse);
public void visit(Keyboard keyboard);
public void visit(Monitor monitor);
}

Step 4.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// ComputerPartDisplayVisitor.java
public class ComputerPartDisplayVisitor implements ComputerPartVisitor{
@Override
public void visit(Computer computer) {
System.out.println("Displaying Computer.");
}
@Override
public void visit(Mouse mouse) {
System.out.println("Displaying Mouse.");
}
@Override
public void visit(Keyboard keyboard) {
System.out.println("Displaying Keyboard.");
}
@Override
public void visit(Monitor monitor) {
System.out.println("Displaying Monitor.");
}
}

Step 5.

1
2
3
4
5
6
7
// VisitorPatternDemo.java
public class VisitorPatternDemo{
public static void main(String[] args){
ComputerPart computer = new Computer();
computer.accept(new ComputerPartDisplayVisitor());
}
}

Example Statement

  • Compiler and AST,
    • There are several nodes in an abstract syntax tree (AST), such as VariableRefNode and AssignmentNode, which represent respective parts in source code and keep the code information.
    • Each node currently provides three interfaces for the compiler to use in order to check its type, generate code and print out the content.
  • Nutrition Retrieval from A Restaurant Menu,
    • The menu components of the Diner restaurant which comprises menu items and diner menus can be printed by a waitress.
    • Each diner menu consists of several menu items.
    • The Diner restaurant would like to provide calories, protein and carbs information for each menu item.
  • Equipment Power Consumption,
    • There are three types of equipment in the inventory, such as chassis, buses, and floppies. Among all the equipment, Chassis is composited of others.
    • Chassis provides an interface for the creation of an iterator, which iterates all the equipment in one chassis with next and hasNext operations.
    • Each equipment provides its power consumption and cost in addition.
    • Chassis provides a sum of power consumption or cost for all its components.

Singleton Pattern

Design Aspect

the sole instance of a class

  • Ensure a class only has one instance, and provide a global point of access to it

Problem

  • It’s important for some classes to have exactly one instance and ensure that the instance is easily accessible.
  • A global variable makes an object accessible, but it doesn’t keep you from instantiating multiple objects.

Graph

Steps

Step 1.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// SingleObject.java
public class SingleObject{
private static SingleObject instance = new SingleObject();
private SingleObject(){}
public static SingleObject getInstance(){
return instance;
}
public void showMessage(){
System.out.println("Hello World!");
}
}

Step 2.

1
2
3
4
5
6
7
// SingletonPatternDemo.java
public class SingletonPatternDemo{
public static void main(String[] args){
SingleObject object = SingleObject.getInstance();
object.showMessage();
}
}

Example Statement

  • Chocolate Boiler,
    • A chocolate boiler is used to boil chocolate.
    • Before boiling chocolate with the boiler, you have to make sure that the boiler is now empty and then fill chocolate in. Besides, you can’t boil chocolate again while the chocolate has already been boiled.
    • After boiling, it is time to drain out the boiled chocolate and make the boiler empty again.
    • In order to prevent some unexpected situation, it is not allowed to have multiple instances of the chocolate boiler in the system.

FlyWeight Pattern

Design Aspect

Storage costs of objects

  • Use sharing to support large numbers of finegrained objects efficiently.

Problem

  • Some applications could benefit from using objects throughout their design, but a naive implementation would be prohibitively expensive.

Graph

Steps

Step 1.

1
2
3
4
// Shape.java
public interface Shape{
void draw();
}

Step 2.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// Circle.java
public class Circle implements Shape{
private String color;
private int x;
private int y;
private int radius;
public Circle(String color){
this.color = color;
}
public void setX(int x){
this.x = x;
}
public void setY(int y){
this.y = y;
}
public void setRadius(int radius){
this.radius = radius;
}
@Override
public void draw(){
System.out.println("Circle: draw() [ Color: " + color + ", x: " + x + ", y: " + y + ", radius: " + radius + "]");
}
}

Step 3.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// ShapeFactory.java
import java.util.HashMap;
public class ShapeFactory{
private static final HashMap<String, Shape> circleMap = new HashMap();
public static Shape getCircle(String color){
Circle circle = (Circle)circleMap.get(color);
if (circle == null){
circle = new Circle(color);
circleMap.put(color, circle);
System.out.println("Creating circle of color: " + color);
}
return circle;
}
}

Step 4.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// FlyWeightPatternDemo.java
public class FlyWeightPatternDemo{
public static final String colors[] = {"Red", "Green", "Blue", "White", "Black"};
public static void main(Sting[] args){
for (int i = 0; i < 20; i++){
Circle circle = (Circle)ShapeFactory.getCircle(getRandomColor());
circle.setX(getRandomX());
circle.setY(getRandomY());
circle.setRadius(100);
circle.draw();
}
}
private static String getRandomColor(){
return colors[(int)(Math.random()*colors.length)];
}
private static int getRandomX() {
return (int)(Math.random()*100 );
}
private static int getRandomY() {
return (int)(Math.random()*100);
}
}

Example Statement

  • Document Editor,
    • A document editor uses objects to represent embedded elements like rows, columns and characters. The characters have X-Y locations, and they can draw themselves dynamically.