Creational design patterns Flashcards

1
Q

Factory Method

A

Factory Method is a creational design pattern that provides an interface for creating objects in a superclass, but allows subclasses to alter the type of objects that will be created.
The Factory Method pattern suggests that you replace direct object construction calls (using the new operator) with calls to a special factory method. Don’t worry: the objects are still created via the new operator, but it’s being called from within the factory method. Objects returned by a factory method are often referred to as products.

At first glance, this change may look pointless: we just moved the constructor call from one part of the program to another. However, consider this: now you can override the factory method in a subclass and change the class of products being created by the method.

There’s a slight limitation though: subclasses may return different types of products only if these products have a common base class or interface. Also, the factory method in the base class should have its return type declared as this interface.

Use the Factory Method when you want to provide users of your library or framework with a way to extend its internal components.
Can substitute inheritance
Use the Factory Method when you want to save system resources by reusing existing objects instead of rebuilding them each time.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

How to Implement factory method

A

Make all products follow the same interface. This interface should declare methods that make sense in every product.

Add an empty factory method inside the creator class. The return type of the method should match the common product interface.

In the creator’s code find all references to product constructors. One by one, replace them with calls to the factory method, while extracting the product creation code into the factory method.

You might need to add a temporary parameter to the factory method to control the type of returned product.

At this point, the code of the factory method may look pretty ugly. It may have a large switch statement that picks which product class to instantiate. But don’t worry, we’ll fix it soon enough.

Now, create a set of creator subclasses for each type of product listed in the factory method. Override the factory method in the subclasses and extract the appropriate bits of construction code from the base method.

If there are too many product types and it doesn’t make sense to create subclasses for all of them, you can reuse the control parameter from the base class in subclasses.

For instance, imagine that you have the following hierarchy of classes: the base Mail class with a couple of subclasses: AirMail and GroundMail; the Transport classes are Plane, Truck and Train. While the AirMail class only uses Plane objects, GroundMail may work with both Truck and Train objects. You can create a new subclass (say TrainMail) to handle both cases, but there’s another option. The client code can pass an argument to the factory method of the GroundMail class to control which product it wants to receive.

If, after all of the extractions, the base factory method has become empty, you can make it abstract. If there’s something left, you can make it a default behavior of the method.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Factory pros

A

You avoid tight coupling between the creator and the concrete products.
Single Responsibility Principle. You can move the product creation code into one place in the program, making the code easier to support.
Open/Closed Principle. You can introduce new types of products into the program without breaking existing client code.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Factory cons

A

The code may become more complicated since you need to introduce a lot of new subclasses to implement the pattern. The best case scenario is when you’re introducing the pattern into an existing hierarchy of creator classes.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Factory Relations with Other Patterns

A

Many designs start by using Factory Method (less complicated and more customizable via subclasses) and evolve toward Abstract Factory, Prototype, or Builder (more flexible, but more complicated).

Abstract Factory classes are often based on a set of Factory Methods, but you can also use Prototype to compose the methods on these classes.

You can use Factory Method along with Iterator to let collection subclasses return different types of iterators that are compatible with the collections.

Prototype isn’t based on inheritance, so it doesn’t have its drawbacks. On the other hand, Prototype requires a complicated initialization of the cloned object. Factory Method is based on inheritance but doesn’t require an initialization step.

Factory Method is a specialization of Template Method. At the same time, a Factory Method may serve as a step in a large Template Method.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Abstract Factory

A

is a creational design pattern that lets you produce families of related objects without specifying their concrete classes.

Use the Abstract Factory when your code needs to work with various families of related products, but you don’t want it to depend on the concrete classes of those products—they might be unknown beforehand or you simply want to allow for future extensibility.

The Abstract Factory provides you with an interface for creating objects from each class of the product family. As long as your code creates objects via this interface, you don’t have to worry about creating the wrong variant of a product which doesn’t match the products already created by your app.

Consider implementing the Abstract Factory when you have a class with a set of Factory Methods that blur its primary responsibility.

In a well-designed program each class is responsible only for one thing. When a class deals with multiple product types, it may be worth extracting its factory methods into a stand-alone factory class or a full-blown Abstract Factory implementation.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Pros Factory method

A

You can be sure that the products you’re getting from a factory are compatible with each other.
You avoid tight coupling between concrete products and client code.
Single Responsibility Principle. You can extract the product creation code into one place, making the code easier to support.
Open/Closed Principle. You can introduce new variants of products without breaking existing client code.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Factory cons

A

The code may become more complicated than it should be, since a lot of new interfaces and classes are introduced along with the pattern.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Abstract Factory relationships

A

Many designs start by using Factory Method (less complicated and more customizable via subclasses) and evolve toward Abstract Factory, Prototype, or Builder (more flexible, but more complicated).

Builder focuses on constructing complex objects step by step. Abstract Factory specializes in creating families of related objects. Abstract Factory returns the product immediately, whereas Builder lets you run some additional construction steps before fetching the product.

Abstract Factory classes are often based on a set of Factory Methods, but you can also use Prototype to compose the methods on these classes.

Abstract Factory can serve as an alternative to Facade when you only want to hide the way the subsystem objects are created from the client code.

You can use Abstract Factory along with Bridge. This pairing is useful when some abstractions defined by Bridge can only work with specific implementations. In this case, Abstract Factory can encapsulate these relations and hide the complexity from the client code.

Abstract Factories, Builders and Prototypes can all be implemented as Singletons.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Builder method

A

is a creational design pattern that lets you construct complex objects step by step. The pattern allows you to produce different types and representations of an object using the same construction code.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Builder solution

A

The Builder pattern suggests that you extract the object construction code out of its own class and move it to separate objects called builders.
The pattern organizes object construction into a set of steps (buildWalls, buildDoor, etc.). To create an object, you execute a series of these steps on a builder object. The important part is that you don’t need to call all of the steps. You can call only those steps that are necessary for producing a particular configuration of an object.

Some of the construction steps might require different implementation when you need to build various representations of the product. For example, walls of a cabin may be built of wood, but the castle walls must be built with stone.

In this case, you can create several different builder classes that implement the same set of building steps, but in a different manner. Then you can use these builders in the construction process (i.e., an ordered set of calls to the building steps) to produce different kinds of objects.

For example, imagine a builder that builds everything from wood and glass, a second one that builds everything with stone and iron and a third one that uses gold and diamonds. By calling the same set of steps, you get a regular house from the first builder, a small castle from the second and a palace from the third. However, this would only work if the client code that calls the building steps is able to interact with builders using a common interface.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

Director

A

You can go further and extract a series of calls to the builder steps you use to construct a product into a separate class called director. The director class defines the order in which to execute the building steps, while the builder provides the implementation for those steps.
Having a director class in your program isn’t strictly necessary. You can always call the building steps in a specific order directly from the client code. However, the director class might be a good place to put various construction routines so you can reuse them across your program.

In addition, the director class completely hides the details of product construction from the client code. The client only needs to associate a builder with a director, launch the construction with the director, and get the result from the builder.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

Design pattern

A

A standard solution to a common
software problem in a context.
* describes a recurring software structure or idiom
* is abstract from any particular programming language
* identifies classes and their roles in the solution to a
problem

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

In general, a pattern has four essential elements.

A

The pattern name
▪ The problem
▪ The solution
▪ The consequences

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

The Pattern Name

A

The pattern name is a handle we can use to describe a
design problem, its solutions, and consequences in a
word or two.
▪ Naming a pattern immediately increases the design
vocabulary. It lets us design at a higher level of
abstraction.
▪ Having a vocabulary for patterns lets us talk about
them.
▪ It makes it easier to think about designs and to
communicate them and their trade-offs to others.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

The problem

A

describes when to apply the pattern.
▪ It explains the problem and its context.
▪ It might describe specific design problems such as how to
represent algorithms as objects.
▪ It might describe class or object structures that are
symptomatic of an inflexible design.
▪ Sometimes the problem will include a list of conditions that
must be met before it makes sense to apply the pattern.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q

The solution

A

describes the elements that make up the design, their
relationships, responsibilities, and collaborations.
▪ The solution doesn’t describe a particular concrete design or
implementation, because a pattern is like a template that can be
applied in many different situations.
▪ Instead, the pattern provides an abstract description of a design
problem and how a general arrangement of elements (classes
and objects in our case) solves it

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
18
Q

The consequences

A

are the results and trade-offs of applying the
pattern.
▪ The consequences for software often concern space and time
trade-offs.
▪ They may address language and implementation issues as well.
▪ Since reuse is often a factor in object-oriented design, the
consequences of a pattern include its impact on a system’s
flexibility, extensibility, or portability.
▪ Listing these consequences explicitly helps you understand and
evaluate them.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
19
Q

Benefits of using patterns

A
  • Patterns give a design common vocabulary for software
    design:
  • Allows engineers to abstract a problem and talk about that
    abstraction in isolation from its implementation.
  • A culture; domain-specific patterns increase design speed.
  • Capture expertise and allow it to be communicated:
  • Promotes design reuse and avoid mistakes.
  • Makes it easier for other developers to understand a system.
  • Improve documentation (less is needed):
  • Improve understandability (patterns are described well, once).
20
Q

Gang of Four (GoF) patterns

A

Erich Gamma, Richard Helm, Ralph Johnson and John
Vlisides in their Design Patterns book define 23 design
patterns divided into three types:
▪ Creational patterns are ones that create objects for you,
rather than having you instantiate objects directly. This
gives your program more flexibility in deciding which
objects need to be created for a given case.
▪ Structural patterns help you compose groups of objects
into larger structures, such as complex user interfaces or
accounting data.
▪ Behavioral patterns help you define the communication
between objects in your system and how the flow is
controlled in a complex program

21
Q

Creational Patterns

A

abstracting the object-instantiation process
* Singleton Factory
* Builder Prototype

22
Q

Structural Patterns

A

(how objects/classes can be combined)
* Adapter Bridge Composite
* Decorator Facade Flyweight
* Proxy

23
Q

Behavioral Patterns

A

Behavioral Patterns
(communication between objects)
* Command Interpreter Iterator
* Observer State
* Visitor Even-driven …

24
Q

Singleton pattern

A
  • singleton: An object that is the only object of its type.
    (one of the most known / popular design patterns)
  • Ensuring that a class has at most one instance.
  • Providing a global access point to that instance.
  • e.g. Provide an accessor method that allows users to see the instance.
  • Benefits:
  • Takes responsibility of managing that instance away from the
    programmer (illegal to construct more instances).
  • Saves memory.
  • Avoids bugs arising from multiple instances.
25
Q

Restricting objects Singleton

A
  • One way to avoid creating objects: use static methods
  • Examples: Math, System
  • Is this a good alternative choice? Why or why not?
  • Disadvantage: Lacks flexibility.
  • Static methods can’t be passed as an argument, nor
    returned.
  • Disadvantage: Cannot be extended.
  • Static methods can’t be subclassed and overridden like an
    object’s methods could be.
26
Q

Implementing Singleton

A
  • Make constructor(s) private so that they can not be
    called from outside by clients.
  • Declare a single private static instance of the class.
  • Write a public getInstance() or similar method that
    allows access to the single instance.
  • May need to protect / synchronize this method to ensure
    that it will work in a multi-threaded program.
27
Q
A
28
Q

Association UML

A

Association relationship is denoted using an arrow.
Association can exist between two or more classes in UML. There can be one-one, one-many, many-one, and many-many association present between the association classes. In an association relationship, one or more objects can be associated with each other. Objects are linked with each other. In UML Association, deleting one element may or may not affect another associated element. Example:
A teacher is associated with multiple students.
Or
a teacher provides instructions to the students.

29
Q

Aggregation

A

Aggregation relationship is denoted using a straight line with an empty arrowhead at one end. Aggregation is a part of an association relationship. Aggregation is considered as a weak type of association.
In an aggregation relationship, objects that are associated with each other can remain in the scope of a system without each other.
Linked objects are not dependent upon the other object. In UML Aggregation, deleting one element does not affect another associated element. Example:
A car needs a wheel, but it doesn’t always require the same wheel. A car can function adequately with another wheel as well.

30
Q

Composition

A

Composition relationship is denoted using a straight line with a filled arrowhead at any one of the ends. The composition is a part of an association relationship. The composition is considered as a strong type of association. In a composition relationship, objects that are associated with each other cannot remain in the scope without each other. Objects are highly dependent upon each other. In UML Composition, deleting one element affects another associated element. Example:
A file is placed inside the folder. If one deletes the folder, then the file associated with that given folder is also deleted.

31
Q

Singleton example

A
  • Class RandomGenerator generates random numbers.
    public class RandomGenerator {
    private static final RandomGenerator gen =
    new RandomGenerator();
    public static RandomGenerator getInstance() {
    return gen;
    }
    private RandomGenerator() {}

    }
32
Q

Lazy initialization

A

Can wait until client asks for the instance to create it:
public class RandomGenerator {
private static RandomGenerator gen = null;
public static RandomGenerator getInstance() {
if (gen == null) {
gen = new RandomGenerator();
}
return gen;
}
private RandomGenerator() {}

}

33
Q

factory method

A

creates object without showing off instatiation logic to client

34
Q

Using a Factory Pattern

A

You should consider using a Factory pattern when:
▪ Create objects dynamically
▪ A class can’t anticipatewhich kind of class of objectsit must create.
▪ A class uses its subclassesto specify which objectsit creates.
▪ You want to localize the knowledge of which class gets created.
There are severalsimilarvariations on the factory pattern to recognize:
▪ The base class is abstract and the pattern must return a complete working class.
▪ The base class contains default methods and is only subclassed for cases where
the default methods are insufficient.
▪ Parameters are passed to the factory telling it which of several class types to
return. In this case the classes may share the same method names but may do
something quite different.

35
Q

The Abstract Factory Pattern
How does it Work?

A

The Abstract Factory pattern is one level of abstraction higher than the factory
pattern. This pattern returns one of several related classes, each of which can
return several different objects on request. In other words, the Abstract Factory
is a factory object that returns one of several factories.
One classic application of the abstract factory is the case where your system
needs to support multiple “look-and-feel” user interfaces, such as Windows, Motif
or Macintosh:
▪ You tell the factory that you want your program to look like Windows and it
returns a GUI factory which returnsWindows-like objects.
▪ When you request specific objects such as buttons, check boxes and
windows, the GUI factory returns Windows instances of these visual
interface components.

36
Q

A Garden Maker Factory

A

Suppose you are writing a program to plan the layout of gardens. These could be
annual gardens, vegetable gardens or perennial gardens. However, no matter
which kind of garden you are planning, you want to ask the same questions:
▪ What are good border plants?
▪ What are good center plants?
▪ What plants do well in partial shade?
We want a base Garden class that can answer these questions:
public abstract class Garden {
public abstract Plant getCenter();
public abstract Plant getBorder();
public abstract Plant getShade();
}
The Plant class simply contains and returns the plant name:
public class Plant {
String name;
public Plant(String pname) {
name = pname; //save name
}
public String getName() {
return name;
}
}
A Garden class simply returns one kind of each plant. So, for example, for the
vegetable garden we simply write:
public class VegieGarden extends Garden {
public Plant getShade() {
return new Plant(“Broccoli”);
}
public Plant getCenter() {
return new Plant(“Corn”);
}
public Plant getBorder() {
return new Plant(“Peas”);
}
}
We create a series of Garden classes - VegieGarden, PerennialGarden, and
AnnualGarden, each of which returns one of several Plant objects. Next, we
construct our abstract factory to return an object instantiated from one of these
Garden classes and based on the string it is given as an argument:
class GardenMaker {
//Abstract Factory which returns one of three gardens
private Garden gd;
public Garden getGarden(String gtype) {
gd = new VegieGarden(); //default
if(gtype.equals(“Perennial”))
gd = new PerennialGarden();
if(gtype.equals(“Annual”))
gd = new AnnualGarden();
return gd;
}

37
Q

Consequences of Abstract Factory

A

One of the main purposes of the Abstract Factory is that it
isolates the concrete classes that are generated.
▪ The actual class names of these classes are hidden in the factory
and need not be known at the client level at all.
▪ Because of the isolation of classes, you can change or interchange
these product class families freely.
▪ Since you generate only one kind of concrete class, this system
keeps you for inadvertently using classes from different families
of products.
▪ While all of the classes that the Abstract Factory generates have
the same base class, there is nothing to prevent some derived
classes from having additional methods that differ from the
methods of other classes.

38
Q

Prototype or clone

A

Prototype is a creational design pattern that lets you copy existing objects without making your code dependent on their classes.

39
Q

Prototype problem

A

Say you have an object, and you want to create an exact copy of it. How would you do it? First, you have to create a new object of the same class. Then you have to go through all the fields of the original object and copy their values over to the new object.

Nice! But there’s a catch. Not all objects can be copied that way because some of the object’s fields may be private and not visible from outside of the object itself.

There’s one more problem with the direct approach. Since you have to know the object’s class to create a duplicate, your code becomes dependent on that class. If the extra dependency doesn’t scare you, there’s another catch. Sometimes you only know the interface that the object follows, but not its concrete class, when, for example, a parameter in a method accepts any objects that follow some interface.

40
Q

Prototype solution

A

The Prototype pattern delegates the cloning process to the actual objects that are being cloned. The pattern declares a common interface for all objects that support cloning. This interface lets you clone an object without coupling your code to the class of that object. Usually, such an interface contains just a single clone method.

The implementation of the clone method is very similar in all classes. The method creates an object of the current class and carries over all of the field values of the old object into the new one. You can even copy private fields because most programming languages let objects access private fields of other objects that belong to the same class.

An object that supports cloning is called a prototype. When your objects have dozens of fields and hundreds of possible configurations, cloning them might serve as an alternative to subclassing.

Here’s how it works: you create a set of objects, configured in various ways. When you need an object like the one you’ve configured, you just clone a prototype instead of constructing a new object from scratch.

Real-World Analogy
In real life, prototypes are used for performing various tests before starting mass production of a product. However, in this case, prototypes don’t participate in any actual production, playing a passive role instead.
Since industrial prototypes don’t really copy themselves, a much closer analogy to the pattern is the process of mitotic cell division (biology, remember?). After mitotic division, a pair of identical cells is formed. The original cell acts as a prototype and takes an active role in creating the copy.

41
Q

Prototype Applicability

A

Use the Prototype pattern when your code shouldn’t depend on the concrete classes of objects that you need to copy.

This happens a lot when your code works with objects passed to you from 3rd-party code via some interface. The concrete classes of these objects are unknown, and you couldn’t depend on them even if you wanted to.

The Prototype pattern provides the client code with a general interface for working with all objects that support cloning. This interface makes the client code independent from the concrete classes of objects that it clones.

Use the pattern when you want to reduce the number of subclasses that only differ in the way they initialize their respective objects.

Suppose you have a complex class that requires a laborious configuration before it can be used. There are several common ways to configure this class, and this code is scattered through your app. To reduce the duplication, you create several subclasses and put every common configuration code into their constructors. You solved the duplication problem, but now you have lots of dummy subclasses.

The Prototype pattern lets you use a set of pre-built objects configured in various ways as prototypes. Instead of instantiating a subclass that matches some configuration, the client can simply look for an appropriate prototype and clone it.

42
Q

Prototype how to implement

A

Create the prototype interface and declare the clone method in it. Or just add the method to all classes of an existing class hierarchy, if you have one.

A prototype class must define the alternative constructor that accepts an object of that class as an argument. The constructor must copy the values of all fields defined in the class from the passed object into the newly created instance. If you’re changing a subclass, you must call the parent constructor to let the superclass handle the cloning of its private fields.

If your programming language doesn’t support method overloading, you won’t be able to create a separate “prototype” constructor. Thus, copying the object’s data into the newly created clone will have to be performed within the clone method. Still, having this code in a regular constructor is safer because the resulting object is returned fully configured right after you call the new operator.

The cloning method usually consists of just one line: running a new operator with the prototypical version of the constructor. Note, that every class must explicitly override the cloning method and use its own class name along with the new operator. Otherwise, the cloning method may produce an object of a parent class.

Optionally, create a centralized prototype registry to store a catalog of frequently used prototypes.

You can implement the registry as a new factory class or put it in the base prototype class with a static method for fetching the prototype. This method should search for a prototype based on search criteria that the client code passes to the method. The criteria might either be a simple string tag or a complex set of search parameters. After the appropriate prototype is found, the registry should clone it and return the copy to the client.

Finally, replace the direct calls to the subclasses’ constructors with calls to the factory method of the prototype registry.

43
Q

Prototype pros

A

You can clone objects without coupling to their concrete classes.
You can get rid of repeated initialization code in favor of cloning pre-built prototypes.
You can produce complex objects more conveniently.
You get an alternative to inheritance when dealing with configuration presets for complex objects.

44
Q

Prototype cons

A

Cloning complex objects that have circular references might be very tricky.

45
Q

Prototype with other patterns

A

Many designs start by using Factory Method (less complicated and more customizable via subclasses) and evolve toward Abstract Factory, Prototype, or Builder (more flexible, but more complicated).

Abstract Factory classes are often based on a set of Factory Methods, but you can also use Prototype to compose the methods on these classes.

Prototype can help when you need to save copies of Commands into history.

Designs that make heavy use of Composite and Decorator can often benefit from using Prototype. Applying the pattern lets you clone complex structures instead of re-constructing them from scratch.

Prototype isn’t based on inheritance, so it doesn’t have its drawbacks. On the other hand, Prototype requires a complicated initialization of the cloned object. Factory Method is based on inheritance but doesn’t require an initialization step.

Sometimes Prototype can be a simpler alternative to Memento. This works if the object, the state of which you want to store in the history, is fairly straightforward and doesn’t have links to external resources, or the links are easy to re-establish.

Abstract Factories, Builders and Prototypes can all be implemented as Singletons.

46
Q

How to implement Singleton

A

Add a private static field to the class for storing the singleton instance.

Declare a public static creation method for getting the singleton instance.

Implement “lazy initialization” inside the static method. It should create a new object on its first call and put it into the static field. The method should always return that instance on all subsequent calls.

Make the constructor of the class private. The static method of the class will still be able to call the constructor, but not the other objects.

Go over the client code and replace all direct calls to the singleton’s constructor with calls to its static creation method.