0%

Creational Patterns

Creational patterns provide a way to create objects while hiding the creation logic, rather than instantiating objects directly using new operator. This gives program more flexibility in deciding which objects need to be created for a given use case.

Factory Method Pattern

With factory pattern, objects are created without exposing the creation logic to the client. It refers to the factory method that encapsulates the creation of objects such that factory method can be override in a subclass.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class MazeGame {
public MazeGame() {
Room room1 = makeRoom();
Room room2 = makeRoom();
room1.connect(room2);
this.addRoom(room1);
this.addRoom(room2);
}

protected Room makeRoom() {
return new OrdinaryRoom();
}
}

public class MagicMazeGame extends MazeGame {
@Override
protected Room makeRoom() {
return new MagicRoom();
}
}

Abstract Factory Pattern

Abstract factory pattern works around a super factory which creates other factories. This factory is also called the factory of factories.

此处输入图片的描述

此处输入图片的描述

The method createButton on the GuiFactory interface returns objects of type Button. What implementation of Button is returned depends on which implementation of GuiFactory is handling the method call.

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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
interface Button {
void paint();
}
//Abstract Product
interface Label {
void paint();
}

//Abstract Factory
interface GUIFactory {
Button createButton();
Label createLabel();
}

//Concrete Factory
class WinFactory implements GUIFactory {
public Button createButton() {
return new WinButton();
}

public Label createLabel() {
return new WinLabel();
}
}

//Concrete Factory
class OSXFactory implements GUIFactory {
public Button createButton() {
return new OSXButton();
}

public Label createLabel() {
return new OSXLabel();
}

}

//Concrete Product
class OSXButton implements Button {
public void paint() {
System.out.println("I'm an OSXButton");
}
}

//Concrete Product
class WinButton implements Button {
public void paint() {
System.out.println("I'm a WinButton");
}
}

//Concrete Product
class OSXLabel implements Label {
public void paint() {
System.out.println("I'm an OSXLabel");
}
}

//Concrete Product
class WinLabel implements Label {
public void paint() {
System.out.println("I'm a WinLabel");
}
}

//Client application is not aware about the how the product is created. Its only responsible to give a name of
//concrete factory
class Application {
public Application(GUIFactory factory) {
Button button = factory.createButton();
Label label = factory.createLabel();
button.paint();
label.paint();
}
}

public class ApplicationRunner {
public static void main(String[] args) {
new Application(createOsSpecificFactory());
}

public static GUIFactory createOsSpecificFactory() {
String osname = System.getProperty("os.name").toLowerCase();
if(osname != null && osname.contains("windows"))
return new WinFactory();
else
return new OSXFactory();
}
}

Singleton Pattern

Singleton pattern is a design pattern that restricts the instantiation of a class to one object. This is useful when exactly one object is needed to coordinate actions across the system.

  • The Abstract Factory, Builder, and Prototype patterns can use Singletons in their implementation.
  • Facade objects are often singletons because only one Facade object is required.
  • State objects are often singletons.
  • Singletons are often preferred to global variables because:
    • They do not pollute the global namespace (or, in languages with namespaces, their containing namespace) with unnecessary variables.
    • They permit lazy allocation and initialization, whereas global variables in many languages will always consume resources.

      Eager Initialization

      1
      2
      3
      4
      5
      6
      7
      class Singleton {
      private static final Singleton instance = new Singleton();
      private Singleton() {}
      public static Singleton getInstance() {
      return instance;
      }
      }

      Lazy Initialization

      1
      2
      3
      4
      5
      6
      7
      8
      9
      class Singleton {
      private Singleton() {}
      private static class Holder {
      private static final Singleton instance = new Singleton();
      }
      public Singleton getInstance() {
      return Holder.instance;
      }
      }

Prototype Pattern

Prototype pattern is used when creation of object directly is costly. For example, an object is to be created after a costly database operation. We can cache the object, returns its clone on next request and update the database when needed thus reducing database calls.

The mitotic division of a cell — resulting in two identical cells — is an example of a prototype that plays an active role in copying itself and thus, demonstrates the Prototype pattern. When a cell splits, two cells of identical genotype result. In other words, the cell clones itself.

此处输入图片的描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public abstract class Prototype {
public abstract Prototype clone();
}

public class ConcretePrototype1 extends Prototype {
@Override
public Prototype clone() {
return super.clone();
}
}

public class ConcretePrototype2 extends Prototype {
@Override
public Prototype clone() {
return super.clone();
}
}

Builder Pattern

Instead of using numerous constructors, the builder pattern uses another object, a builder, that receives each initialization parameter step by step and then returns the resulting constructed object at once.

Builder often builds a composition object. Often, designs start out using Factory Method (less complicated, more customizable, subclasses proliferate) and evolve toward Abstract Factory, Prototype, or Builder (more flexible, more complex) as the designer discovers where more flexibility is needed. Sometimes creational patterns are complementary: Builder can use one of the other patterns to implement which components are built.

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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
 public class StreetMap {
private final Point origin;
private final Point destination;

private final Color waterColor;
private final Color landColor;
private final Color highTrafficColor;
private final Color mediumTrafficColor;
private final Color lowTrafficColor;

public static class Builder {
// Required parameters
private final Point origin;
private final Point destination;

// Optional parameters - initialize with default values
private Color waterColor = Color.BLUE;
private Color landColor = new Color(30, 30, 30);
private Color highTrafficColor = Color.RED;
private Color mediumTrafficColor = Color.YELLOW;
private Color lowTrafficColor = Color.GREEN;

public Builder(Point origin, Point destination) {
this.origin = origin;
this.destination = destination;
}

public Builder waterColor(Color color) {
waterColor = color;
return this;
}

public Builder landColor(Color color) {
landColor = color;
return this;
}

public Builder highTrafficColor(Color color) {
highTrafficColor = color;
return this;
}

public Builder mediumTrafficColor(Color color) {
mediumTrafficColor = color;
return this;
}

public Builder lowTrafficColor(Color color) {
lowTrafficColor = color;
return this;
}

public StreetMap build() {
return new StreetMap(this);
}

}

private StreetMap(Builder builder) {
// Required parameters
origin = builder.origin;
destination = builder.destination;

// Optional parameters
waterColor = builder.waterColor;
landColor = builder.landColor;
highTrafficColor = builder.highTrafficColor;
mediumTrafficColor = builder.mediumTrafficColor;
lowTrafficColor = builder.lowTrafficColor;
}

public static void main(String args[]) {
StreetMap map = new StreetMap.Builder(new Point(50, 50), new Point(100,
100)).landColor(Color.GRAY).waterColor(Color.BLUE.brighter())
.build();
}
}

References

Abstract factory pattern
Factory Method Pattern