0% found this document useful (0 votes)
31 views

Design Patterns - 2562

The document discusses the Prototype design pattern, which specifies that objects can be cloned rather than created, to avoid subclassing of object creators in client applications. The Prototype pattern provides a way to clone objects without knowing their concrete classes. The key aspects are: - Prototype declares an interface for cloning itself. ConcretePrototype implements cloning by returning a copy. - A client asks a prototype to be cloned rather than calling a constructor, avoiding knowledge of concrete classes. - An example shows Document subclasses like XMLDoc that implement clone() to make copies, managed by a DocumentManager factory.
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
31 views

Design Patterns - 2562

The document discusses the Prototype design pattern, which specifies that objects can be cloned rather than created, to avoid subclassing of object creators in client applications. The Prototype pattern provides a way to clone objects without knowing their concrete classes. The key aspects are: - Prototype declares an interface for cloning itself. ConcretePrototype implements cloning by returning a copy. - A client asks a prototype to be cloned rather than calling a constructor, avoiding knowledge of concrete classes. - An example shows Document subclasses like XMLDoc that implement clone() to make copies, managed by a DocumentManager factory.
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 9

Design patterns

Creational Patterns – Prototype Pattern (Object)

Design Patterns an Overview


Design pattern is a general reusable solution to commonly occurring problem in software
design. A design pattern can be transformed directly into code.

Most of the modern languages and tools use object oriented design to accomplish this task of
solving business problems. Designing a software system is challenging because it not only
needs to meet the identified requirements but also needs to be ready for future extensions and
modifications. A software design problem may have more than one solution. However, the
solution you pick should be the best in a given context. That is where design patterns come
into the picture.

A Design pattern usually explained by following methodology

Name – Name expresses the purpose of design pattern and can be uniquely identified among
developers

Intent – It discusses about the pattern. It tells what is the intention of the design pattern

Problem -- The problem 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.

Solution – The solution 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.

Consequences -- his section explains both the positive and negative implications of using the
design pattern. Positive implications might be increased flexibility, lower memory usage,
easier extensibility, support for particular functionality, or simplified usage. Negative
implications might be inefficient behaviour in particular cases, complex class structure for
certain problems, loss of guarantees of system behaviour, or overly general design with
attendant loss of performance or storage costs. It is important that authors of design patterns
present, and readers of design patterns understand, positive as well as negative consequences.
There are three types of design patterns

Creational design patterns

This pattern can be divided into class-creation patterns and object-creational patterns. While
class-creation patterns use inheritance effectively in the instantiation process, object-creation
patterns use delegation effectively to get the job done.

Structural design patterns

This patterns are all about Class and Object composition. Structural class-creation patterns
use inheritance to compose interfaces. Structural object-patterns define ways to compose
objects to obtain new functionality.

Behavioural Design Patterns

This patterns are all about Class's objects communication. Behavioural patterns are those
patterns that are most specifically concerned with communication between objects.

Design Patterns

Creational Structural Behavioural


Design Design Design
Chain of
Patterns Patterns Responsibility
Patterns
Command
Adapter
Interpreter
Abstract Factory Bridge
Iterator
Builder Composite
Mediator
Factory Method Decorator
Memento
Prototype Façade
Observer
Singleton Flyweight
State
Proxy
Strategy
Template
Visitor
Creational Pattern – Prototype Pattern (Object)
Creational Pattern an overview
Creational design patterns abstract the instantiation process. They help make a system
independent of how its objects are created, composed, and represented. A class creational
pattern uses inheritance to vary the class that's instantiated, where as an object creational
pattern will delegate instantiation to another object.

Creational patterns become important as systems evolve to depend more on object


composition than class inheritance. As that happens, emphasis shifts away from hard-coding
a fixed set of behaviours toward defining a smaller set of fundamental
behaviour that can be composed into any number of more complex ones. Thus creating
objects with particular behaviour requires more than simply instantiating a class.

There are two recurring themes in these patterns. First, they all encapsulate knowledge about
which concrete classes the system uses. Second, they hide how instances of these classes are
created and put together. All the system at large
knows about the objects is their interfaces as defined by abstract classes. Consequently, the
creational patterns give you a lot of flexibility in what gets created, who creates it, how it gets
created, and when. They let you configure
a system with "product" objects that vary widely in structure and functionality. Configuration
can be static (that is, specified at compile-time) or dynamic (at run-time).

Sometimes creational patterns are competitors. For example, there are cases when either
Prototype or Abstract Factory could be used profitably. Some times they are complementary:
Builder can use one of the other patterns to implement which components get built. Prototype
can use Singleton in its implementation.

Prototype Pattern
This is a Creational pattern that should be used when the type of objects to create is
determined by a 'prototypical instance', which is cloned to produce new objects.

Avoids sub-classes of an object creator in the client application (like abstract factory does)
Biggest reason for using it is – it avoids inherent cost of creating a new object in the standard
way (via new) in cases where producing initial values for the fields of the object is costly.

Participants and Process

Client - creates a new object by asking a prototype to clone itself.


Prototype - declares an interface for cloning itself.
ConcretePrototype - implements the operation for cloning itself.

The process of cloning starts with an initialized and instantiated class.


The Client asks for a new object of that type and sends the request to the Prototype class.
A ConcretePrototype, depending of the type of object is needed, will handle the cloning
through the Clone() method, making a new instance of itself.
Structure of Prototype pattern

Client Prototype

Operation ( ) Clone ( )

P=Prototype - > Clone ()

Concrete Prototype 1 Concrete Prototype 2 Concrete Prototype 3

Clone ( ) Clone ( ) Clone ( )

Return Copy of Self Return copy of self Return copy of self

Example

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

using namespace std;


const int N = 4;

// Prototype
class Document
{
public:
virtual Document* clone() const = 0;
virtual void store() const = 0;
virtual ~Document() { }
};
// Concrete prototypes : xmlDoc, plainDoc, spreadsheetDoc

class xmlDoc : public Document


{
public:
Document* clone() const { return new xmlDoc; }
void store() const { cout << "xmlDoc\n"; }
};

class plainDoc : public Document


{
public:
Document* clone() const { return new plainDoc; }
void store() const { cout << "plainDoc\n"; }
};

class spreadsheetDoc : public Document


{
public:
Document* clone() const { return new spreadsheetDoc; }
void store() const { cout << "spreadsheetDoc\n"; }
};

// makeDocument() calls Concrete Portotype's clone() method


// inherited from Prototype
class DocumentManager {
public:
static Document* makeDocument( int choice );
~DocumentManager(){}

private:
static Document* mDocTypes[N];
};

Document* DocumentManager::mDocTypes[] =
{
0, new xmlDoc, new plainDoc, new spreadsheetDoc
};

Document* DocumentManager::makeDocument( int choice )


{
return mDocTypes[choice]->clone();
}

// for_each op ()
struct Destruct
{
void operator()(Document *a) const {
delete a;
}
};
// Client
int main() {
vector<Document*> docs(N);
int choice;
cout << "quit(0), xml(1), plain(2), spreadsheet(3): \n";
while (true) {
cout << "Type in your choice (0-3)\n";
cin >> choice;
if (choice <= 0 || choice >= N)
break;
docs[choice] = DocumentManager::makeDocument( choice );
}

for (int i = 1; i < docs.size(); ++i)


if(docs[i]) docs[i]->store();

Destruct d;
// this calls Destruct::operator()
for_each(docs.begin(), docs.end(), d);

return 0; }

OUTPUT

quit(0), xml(1), plain(2),


spreadsheet(3):
Type in your choice (0-3)
1
Type in your choice (0-3)
2
Type in your choice (0-3)
3
Type in your choice (0-3)
0
xmlDoc
plainDoc
spreadsheetDoc
Structure for above example

Client Prototype

Operation ( ) Clone (Document


)

P=Prototype - > Clone ()

Concrete Prototype 1 Concrete Prototype 2 Concrete Prototype 3

Clone ( xml doc) Clone (Plaindoc ) Clone (Spreadsheet )

Return Copy of Self Return copy of self Return copy of self

Participants

Prototype (Document) -- Declares an interface for cloning itself.


ConcretePrototype -- (xmlDoc, Plaindoc, SpreadsheetDoc) implements an operation for
cloning itself.
Client (DocumentManager) -- creates a new object by asking a prototype to clone itself.
Collaborations -- · A client asks a prototype to clone itself

Consequences
Benefits of the Prototype pattern are listed below.

1. Adding and removing products at run-time.


Prototypes let you incorporate a new concrete product class into a system simply by
registering a prototypical instance with the client. That's a bit more flexible than other
creational patterns, because a client can install and remove prototypes at run-time.

2. Specifying new objects by varying values.


Highly dynamic systems let you define new behaviour through object composition—
by specifying values for an object's variables, for example—and not by defining new
classes. You effectively define new kinds of objects by instantiating existing classes
and registering the instances as prototypes of client objects. A client can exhibit new
behaviour by delegating responsibility to the prototype. This kind of design lets users
define new "classes" without programming.
3. Specifying new objects by varying structure.
Many applications build objects from parts and subparts. Editors for circuit design, for
example, build circuits out of subcircuits.1 For convenience, such applications often
let you instantiate complex, user-defined structures, say, to use a specific sub circuit
again and again. The Prototype pattern supports this as well. We simply add this sub
circuit as a prototype to the palette of available circuit elements. As long as the
composite circuit object implements Clone as a deep copy, circuits with different
structures can be prototypes.

4. Reduced subclassing.
The Prototype pattern lets you clone a prototype instead of asking a factory method to
make a new object. Hence you don't need a Creator class hierarchy at all. This benefit
applies primarily to languages like C++ that don't treat classes as first-class objects.
Languages that do, like Smalltalk and Objective C, derive less benefit, since you can
always use a class object as a creator. Class objects already act like prototypes in
these languages.

5. Configuring an application with classes dynamically.


Some run-time environments let you load classes into an application dynamically. The
Prototype pattern is the key to exploiting such facilities in a language like C++. An
application that wants to create instances of a dynamically loaded class won't be able
to reference its constructor statically. Instead, the run-time environment creates an
instance of each class automatically when it's loaded, and it registers the instance with
a prototype manager (see the Implementation section). Then the application can ask
the prototype manager

The main liability of the Prototype pattern is that each subclass of Prototype
must implement the Clone operation, which may be difficult. For example, adding
Clone is difficult when the classes under consideration already exist.
Implementing Clone can be difficult when their internals include objects that
don't support copying or have circular references.

Implementation

Issues when implementing prototypes:

1. Using a prototype manager.


When the number of prototypes in a system isn't fixed (that is, they can be created and
destroyed dynamically), keep a registry of available prototypes. Clients won't manage
prototypes themselves but will store and retrieve them from the registry. A client will
ask the registry for a prototype before cloning it. We call this registry a prototype
manager.

A prototype manager is an associative store that returns the prototype matching a


given key. It has operations for registering a prototype under a key and for un
registering it. Clients can change or even browse through the registry at run-time. This
lets clients extend and take inventory on the system without writing code.

2. Implementing the Clone operation. The hardest part of the Prototype pattern is
implementing the Clone operation correctly. It's particularly tricky when object
structures contain circular references. Most languages provide some support for
cloning objects.

3. Initializing clones. While some clients are perfectly happy with the clone as is, others
will want to initialize some or all of its internal state to values of their choosing. You
generally can't pass these values in the Clone operation, because their number will
vary between classes of prototypes. Some prototypes might need multiple
initialization parameters; others won't need any. Passing parameters in the Clone
operation precludes a uniform cloning interface.

It might be the case that your prototype classes already define operations for
(re)setting key pieces of state. If so, clients may use these operations immediately
after cloning. If not, then you may have to introduce an Initialize operation (see the
Sample Code section) that takes initialization parameters as arguments and sets the
clone's internal state accordingly. Beware of deep-copying Clone operations—the
copies may have to be deleted (either explicitly or within Initialize) before you
reinitialize them.

You might also like