Design Patterns

Design patterns are common, effective solutions to software design problems.

 

Iterator Pattern

An object traverses and accesses elements of a collection, rather than the programmer directly manipulating the collection.

Purpose is to simplify traversal of a collection and hide the details of its inner workings.

Example:

LinkedList list = new LinkedList();
//...add elements...
ListIterator iterator = list.listIterator();
while (iterator.hasNext())
{
     Object element = iterator.next();
     //do something with element
}

This is better than a version of LinkedList that would allow the user to access its nodes directly, like so:

Node node = list.head;
while(node != null)
{
     //do something with node.element
     node = node.next;
}

This is because this complicates things (in working with links) and thus is prone to errors.

In Java, list iterators can be imagined like the cursor in a text processor that moves along characters, the characters being like elements of a list.

Adding element adds it and advances the iterator position by one.

Adding element adds it and advances iterator position by one.

 

Singleton Pattern

A public one-of-a-kind object exists as a static variable.

Purpose is to ensure only one object of a type is publicly available.

Example:

class System
{
     //single God instance.
     static God god = new God(); 
     private class God
     {
          void create()
          {
          }
     }
}

 

Observer Pattern

Henri_Matisse,_1916-17,_Le_Peintre_dans_son_atelier_(The_Painter_and_His_Model),_oil_on_canvas,_146.5_x_97_cm,_Musée_National_d'Art_Moderne,_Centre_Georges_Pompidou,_Paris

An object notifies another object (the “observer”) whenever a change to a data has occurred.

Purpose for this pattern is encapsulation of data and distribution of responsibility.

Example:

//make button.
final JButton button = new JButton();
 
//make observer for mouse events.
MouseListener listener = new MouseAdapter()
{
     public void mouseClicked(MouseEvent e)
     {
          button.setText("clicked");
     }
};
 
//make it observe the button.
button.addMouseListener(listener);

Model-View-Controller (MVC) is an architecture that uses this pattern. Example: visualize a posing artist’s model (Model), a painter of the model (View), and a director of the model (Controller). The director controls the model’s state. Whenever it does, the model notifies the painter to update his representation of the model visible to the user.

Example:

// Model.
class Model
 {
     String state;
     Painter painter; //representer of model
 
     //notify painter when state changed.
     void notify()
     {
          painter.repaint(this);
     }
}
 
// View.
class Painter
{
     void repaint(Model model)
     {
          //update representation of model.
     }
}
 
// Controller.
class Director
{
     Model model;
     Director(Model model)
     {
          this.model = model;
     }

     void setModelState(String newState)
     {
          model.state = newState;
          model.notify();
     }
}

//The tester.
class Tester
{
     public static void main(String[] args)
     {
           Model model = new Model();
           model.painter = new Painter();
           Director director = new Director(model);
           director.setModelState("Sitting");
     }
}

Another way to think of Model-View-Controller, is Data-Output-Input. the input changes the data (as an interface to it), while the output represents the data to the user in whatever state it currently is in.

 

Adapter Pattern

A class (the “adapter”) implements an interface by blank methods to save its users from implementing every method when some are unneeded.

Purpose is nothing more than saving code.

Example:

//make button.
final JButton button = new JButton();
 
//make adapter implementing one method of an interface.
MouseListener listener = new MouseAdapter()
{
     public void mouseClicked(ActionEvent event)
     {
          button.setText("Clicked");
     }
};
button.addMouseListener(listener);

This is the same as, but shorter than, this:

//make button.
final JButton button = new JButton();

//make adapter implementing one method of an interface.
MouseListener listener = new MouseListener()
{
     public void mouseClicked(MouseEvent e)
     {
            button.setText("Clicked");
     }
     
 
     //implement unneeded methods as blank.
     public void mouseMoved(ActionEvent e)
     {  
     }
     public void mouseEntered(MouseEvent e)
     {
     }
 
     public void mouseExited(MouseEvent e)
     {
     }
 
     public void mousePressed(MouseEvent e)
     {
     }
 
     public void mouseReleased(MouseEvent e)
     {
     }
};
button.addMouseListener(listener);

 

Composite Pattern

composite

A class acts a container for its siblings and using this container simply uses all its contained objects, as a proxy.

Example:

abstract class Item
{
     abstract void use();
}
class Toy extends Item
{
     void use()
     {
          System.out.print("Beep!");
     }
}

class Perfume extends Item
{
     void use()
     {
          amount -= 1;
     }
 
     int amount = 10;
}

//Compositing class.
class Bundle extends Item
{
     # held items.
     List items = new ArrayList();
 
     # this simply calls use() of each held item.
     void use()
     {
          for (Item item: items)
              item.use()
     }
}

 

Decorator Pattern

rosiejetsons

A class acts as a container and proxy for a sibling, but also defines new features to enhance it.

This sounds like the Composite pattern, but Composite intends to collect, while Decorator intends to enhance.

Example:

//Class to be decorated.
class Robot
{
     void run()
     {
           ...
     }
}

//Decorating class.
class JetBot extends Robot
{
     //robot to enhance.
     Robot robot;
     JetBot(Robot robot)
     {
          this.robot = robot;
     }

     //enhancing features.      
     int fuel = 100;

     ...
}

 

Command Pattern

An action, in the form of an algorithm, is contained in an object to remember and use the algorithm later.

Example:

abstract class Job
{
     abstract void do();
}
class CleanJob
{
     void do()
     {
          //...
     }
}
class PrintJob
{   
     void do()
     {
          //...
     }
}

 

Strategy Pattern

Different algorithms that fulfill the same goal differently are saved.

Purpose is to save actions for use in different scenarios.

Similar to Command, but Strategy algorithms are intended for one goal, while Command algorithms are for different goals.

Example:

//strategy to sort Accounts.
class AccountComparatorByName implements Comparator<Account>
{
     public int compare(Account first, Account second)
     {
          return first.name.compareTo(second.name);
     }
}
 
//another strategy.
class AccountComparatorByID implements Comparator<Account>
{
     public int compare(Account first, Account second)
     {
          return first.id – second.id;
     }
}
 
//test: make list.
List list = new List();
list.add(new Account(8152, "David"));
list.add(new Account(1372, "Shawn"));
list.add(new Account(3283, "Ruth"));
 
//try sorting strategies.
Collections.sort(list, new AccountComparatorByName());
Collections.sort(list, new AccountComparatorByID());

 

Template Method Pattern

An abstract class contains one concrete method (the “template”) that calls several abstract methods, which are defined by concrete classes.

Example:

abstract class Game
{
     //Template method.
     void play(int players)
     {
          initialize();
          while (!isEnd())
               turn();
     }

     //Abstract methods.
     abstract void initialize();
     abstract void turn();
     abstract boolean isEnd();
}

class Chess extends Game
{
     void initialize()
     {
          //...
     }
     
     void turn()
     {
          //...
     }

     boolean isEnd()
     {
          //...
     }
}

class Poker extends Game
{
     void initialize()
     {
          //...
     }
     
     void turn()
     {

          //...
     }

     boolean isEnd()
     {
          //...
     }
}

 

Factory Method Pattern

A method implements an abstract method for only creating and returning objects.

Example:

abstract class AsexualOrganism
{
     abstract Object reproduce();
}
 
class Virus extends AsexualOrganism
{
     //factory method.
     Object reproduce()
     {
          return new Virus();
     }
}

Example:

//make list.
List list = new LinkedList();
 
//create iterator by the factory method iterator().
Iterator iterator = list.iterator();
 
//iterator() implements List’s method iterator().

 

Abstract Factory Pattern

An abstract class with factory methods has several subclasses in their own object creation theme.

Example: “LookAndFeel” classes for graphical applications

 

Chain Of Responsibility Pattern

Belt-conveyor-handling

Several handlers handle a request in sequence, like workers over a conveyor belt.

Example:

//make button.
final JButton button = new JButton();
 
//make two ActionListeners handling the same event.

ActionListener one = new ActionListener() 
{
     public void actionPerformed(ActionEvent e)      
     {
           System.out.println("Clicked!");
      } 
};

ActionListener two = new ActionListener() 
{
     public void actionPerformed(ActionEvent e)      
     {
          button.setEnabled(false);
      } 
};

button.addActionListener(one);
button.addActionListener(two);

 

Memento Pattern

An object’s old state is saved (like a “snapshot”) to later return to it.

Coupled with the Command Pattern, it is a useful pattern to create undo functionality by.

Example are found in How to Implement Undo/Redo.

 

Proxy Pattern

An object acts an interface (actor on behalf) to another object, being used exactly like that other.

Examples can be found in Adapter, Composite, and Decorator sections above.

Please like & share: