Type Laundering & Prototype Pattern Kunal Chaudhary.

43
Type Laundering & Prototype Pattern Kunal Chaudhary

Transcript of Type Laundering & Prototype Pattern Kunal Chaudhary.

Page 1: Type Laundering & Prototype Pattern Kunal Chaudhary.

Type Laundering&

Prototype PatternKunal Chaudhary

Page 2: Type Laundering & Prototype Pattern Kunal Chaudhary.

Prototype Pattern Dr W. W.

Page 3: Type Laundering & Prototype Pattern Kunal Chaudhary.

Applicability When the classes to instantiate are specified

at run-time, for example, by dynamic loading; or

To avoid building a class hierarchy of factories that parallels the class hierarchy of products; or

It may be more convenient to install a corresponding number of prototypes and clone them rather than instantiating the class manually.

Page 4: Type Laundering & Prototype Pattern Kunal Chaudhary.

Participants Prototype (Graphic)

declares an interface for cloning itself. ConcretePrototype(Staff, WholeNote,

HalfNote)implements an operation for cloning itself.

Client (GraphicTool)creates a new object by asking a prototype to clone itself.

Page 5: Type Laundering & Prototype Pattern Kunal Chaudhary.

UML Diagram

Page 6: Type Laundering & Prototype Pattern Kunal Chaudhary.

Consequences Adding and removing products at run-time. Specifying new objects by varying values. Specifying new objects by varying

structure. Reduced subclassing. Configuring an application with classes

dynamically.

Page 7: Type Laundering & Prototype Pattern Kunal Chaudhary.

Implementation Issues Using a prototype manager. Implementing the Clone operation. Initializing clones.

Page 8: Type Laundering & Prototype Pattern Kunal Chaudhary.

Dr W. W.’s Story It is a painful road to achieve the

success in Dr. W. W’s Diabolical plan to conquer the world.

But he did it using the Prototype Pattern.

Page 9: Type Laundering & Prototype Pattern Kunal Chaudhary.

Multiple Frankesteins from a Prototype So, the cloning machine looks like this:class CloningMachine {

function CloningMachine( ) { }

public function buildClone( ): frankenstein {

return new frankenstein( ); }

public function buildManyClones( cloneNum: Number ) {

var returnArray: Array = new Array( );

for( var k=0; k< clonesNum; k++ ) {

returnArray[ k ] = new frankenstein( ); } return returnArray;

} }

Page 10: Type Laundering & Prototype Pattern Kunal Chaudhary.

Code!

And the frankenstein will be like:class frankenstein { function frankenstein( ) {

trace( "beeeee. I'm a new frankenstein" );

} }

Page 11: Type Laundering & Prototype Pattern Kunal Chaudhary.
Page 12: Type Laundering & Prototype Pattern Kunal Chaudhary.

Smart plan again (still lacks…..) So, he decides to add the functionality needed to clone horses.

How?. Look class CloningMachine { function CloningMachine( ) { } public function buildClone( ): frankenstein { return new frankenstein( ); } public function buildhorseClone( ): horse { return new horse( ); } public function buildManyClones( cloneNum: Number ) { var returnArray: Array = new Array( ); for( var k=0; k< clonesNum; k++ ) { returnArray[ k ] = new frankenstein( ); } return returnArray; } }

Page 13: Type Laundering & Prototype Pattern Kunal Chaudhary.

AAAAGGHHHHH!!!!!

Page 14: Type Laundering & Prototype Pattern Kunal Chaudhary.

A new idea, but not enough After thinking about the problem carefully,

Professor W.W. gives it another try: class CloningMachine { function CloningMachine( ) { } public function buildClone( type: String ): Object { if( type == "frankenstein" ) { return new frankenstein( ); } else if ( type == "horse" ) { return new horse( ); } } public function buildManyClones( cloneNum: Number ) { var returnArray: Array = new Array( ); for( var k=0; k< clonesNum; k++ ) { returnArray[ k ] = new frankenstein( ); } return returnArray; } }

Page 15: Type Laundering & Prototype Pattern Kunal Chaudhary.

Look Below… So, here’s a frankenstein:class frankenstein implements ICloneable

{ function frankenstein( ) { trace( "Hi, I will be cloned soon" ); } public function clone( ): ICloneable { trace( "Beeee, I'm a new frankenstein" ); return new frankenstein( ); } public function toString( ): String { return "{ Hi, I'm a frankenstein. }"; } }

Page 16: Type Laundering & Prototype Pattern Kunal Chaudhary.

Horse Implementation And here’s a horse:class horse implements ICloneable { function horse( initFlag: Boolean ) { trace( "Muuuu, I'm a horse. I will also be cloned

soon" ); if( initFlag == true ) { init( ); } } private function init( ) { trace( "I'm an initialized horse, whatever that

means" ); } public function clone( ): ICloneable { return new horse( true ); } public function toString( ): String { return "{ Yes, I'm a cloned horse, muuuuuu }"; } }

Page 17: Type Laundering & Prototype Pattern Kunal Chaudhary.

New Cloning Machine And Professor W.W. will want to do something like this:var cMachine: CloningMachine = new CloningMachine( ); cMachine.buildClone( new frankenstein( ) ); cMachine.buildClone( new horse( ) ); trace( "--" ); var frankensteinClones: Array =

cMachine.buildManyClones( 5, new frankenstein( ) ); var horseClones: Array = cMachine.buildManyClones( 5,

new horse( ) ); trace( "--" ); trace( "frankensteinClones " + frankensteinClones ); trace( "horseClones " + horseClones );

Page 18: Type Laundering & Prototype Pattern Kunal Chaudhary.

Cloning, continued… So, finally, the cloning machine will be able to receive an animal ( an

instance of a class ), and tell it to create as many copies of itself as needed:

class CloningMachine { function CloningMachine( ) { } public function buildClone( template: ICloneable ):

ICloneable { return template.clone( ); } public function buildManyClones( clonesNum: Number,

template: ICloneable ): Array { var returnArray: Array = new Array( ); for( var k=0; k< clonesNum; k++ ) { returnArray[ k ] = template.clone( ); } return returnArray; } }

Page 19: Type Laundering & Prototype Pattern Kunal Chaudhary.

Bad News !!! Dr. W. W. lost and still didn’t win over the

world because apparently GOODNESS WINS OVER PROTOTYPE PATTERN!!!!!

Page 20: Type Laundering & Prototype Pattern Kunal Chaudhary.

Good uses of Prototype pattern The first widely known application of

the pattern in an object-oriented language was in ThingLab, where users could form a composite object and then promote it to a prototype by installing it in a library of reusable objects.

Page 21: Type Laundering & Prototype Pattern Kunal Chaudhary.

Related Patterns Prototype and Abstract Factory are

competing patterns in some ways.They can also be used together, however. An Abstract Factory might store a set of prototypes from which to clone and return products objects.

Designs that make heavy use of the Composite and Decorator patterns often can benefit from Prototype as well.

Page 22: Type Laundering & Prototype Pattern Kunal Chaudhary.

Type Laundering If you are using the dynamic cast

again and again because your framework does not let you make the extensions to its interfaces then my friend you have bugs in your design.

Page 23: Type Laundering & Prototype Pattern Kunal Chaudhary.

Good News! You can turn those bugs into useful

features.

Thanks to type laundering!

Page 24: Type Laundering & Prototype Pattern Kunal Chaudhary.

Example Take the vending machine. Its CoinInsertedEvent

subclass adds a Cents getCoin() operation that returns the value of the coin a customer deposited. Another kind of event, CoinReleaseEvent, gets instantiated when the customer wants his or her money back. These operations and others would be implemented using rep. Clients of these events could of course use rep directly, assuming it's public.

But there's little reason to make it so: rep offers almost no abstraction, and it makes clients work pretty hard to get at the information they need. More likely, rep would be protected---of interest only to subclasses, which use it to implement more specialized interfaces.

Page 25: Type Laundering & Prototype Pattern Kunal Chaudhary.

Dealing with Loss Since there is no universal interface for

events, all that the framework knows about events is that they implement a basic interface because events are defined long after the framework is designed.

There are 2 questions that arise:How does the framework create instances of domain-specific subclasses? How does application code access subclass-specific operations when all it gets from the framework is objects of type Event?

Page 26: Type Laundering & Prototype Pattern Kunal Chaudhary.

1st Answer Answer to the 1st question lies in

defining one of the many creational patterns within the framework.Example: By defining factory method pattern in the framework, a new instance of domain-specific Event subclass can be obtained.

Page 27: Type Laundering & Prototype Pattern Kunal Chaudhary.

2nd Answer Answer to the 2nd question lies in

another question, which is, are there patterns for recovering type information from an instance?

Using visitor pattern lost type information can be recovered without resorting to dynamic casts to do the same.

Page 28: Type Laundering & Prototype Pattern Kunal Chaudhary.

Celebrate Adversity The whole point is to use the loss of

type information to our advantage and not mourn about it.

Lets leave event for now and lets move on the issues in the memento pattern.

Page 29: Type Laundering & Prototype Pattern Kunal Chaudhary.

What is Memento?(Small review) Memento captures and externalizes

an object’s state in order to restore the object to the same state at a later time.

Externalization must not violate encapsulation.

Page 30: Type Laundering & Prototype Pattern Kunal Chaudhary.

Cursor ExampleHere is an example:Structure s; Cursor c;

for (s.first(c); s.more(c); s.next(c)) { Element e = s.element(c); // use Element e } The cursor has no client-accessible operations.

The way to the pull this off is to give the object two different interfaces in C++.

Page 31: Type Laundering & Prototype Pattern Kunal Chaudhary.

A Need in Friend Using the friend keyword allows access to a broad interface

while limiting access to other classes.class Cursor { public: virtual ~Cursor(); private: friend class Structure; Cursor () { _current = 0; } ListElem* current () { return _current; } // gets _current void current (ListElem* e) { _current = e; } // sets _current private: ListElem* _current; };

Page 32: Type Laundering & Prototype Pattern Kunal Chaudhary.

Better Code In this case, structure operations manipulate _current to keep

track of the point in the traversal .class Structure { // ... virtual void first (Cursor& c) { c.current(_head); // _head is the head of the linked list, // which Structure keeps internally } virtual bool more (Cursor& c) { return c.current()->_next != 0; } virtual void next (Cursor& c) { c.current(c.current()->_next); // set current to next ListElem* } virtual Element& element (Cursor& c) { return c.current()->_element; } // ... };

Page 33: Type Laundering & Prototype Pattern Kunal Chaudhary.

Problems in Memento The memento pattern furrows away only that

much information in cursor memento which is necessary to mark the current stage of traversal.

A shortcoming is that substructure code cannot access cursor’s covert interface.

It cannot implement other cursor dependent functionality because it cannot override the cursor-handling operations inherited from structure.

Page 34: Type Laundering & Prototype Pattern Kunal Chaudhary.

Alternate way One work around is to define protected

operations in structure.class Structure { // ... protected: ListElem* current (Cursor& c) { return c.current(); } void current (Cursor& c, ListElem* e) { c.current(e); } // ... }; It extends structures privileges to its subclasses.

Page 35: Type Laundering & Prototype Pattern Kunal Chaudhary.

Event’s loss is Cursor’s Gain The way we transform a design bug into a

feature is known as type laundering and this is how it is done:The idea is to define an abstract base class for Cursor that includes only those aspects of its interface that should be public.class Cursor {public: virtual ~Cursor () { } protected: Cursor () { } };

Page 36: Type Laundering & Prototype Pattern Kunal Chaudhary.

progress in the Cursor Example Just so that the cursor acts as an abstract class, the

constructor is protected to preclude instantiation.class ListCursor : public Cursor { public: ListCursor () { _current = 0; } ListElem* current () { return _current; } void current (ListElem* e) { _current = e; } private: ListElem* _current; };

Page 37: Type Laundering & Prototype Pattern Kunal Chaudhary.

Better Arrangement This arrangement means that Structure operations

that take a Cursor as an argument must downcast it to a ListCursor before they can access the extended interface: class Structure { // ... virtual void first (Cursor& c) { ListCursor* lc; if (lc = dynamic_cast<ListCursor*>(&c)) { lc->current(_head); // _head is the head of the linked list, // which Structure keeps internally } } // ... };

Page 38: Type Laundering & Prototype Pattern Kunal Chaudhary.

Instantiation The final task to this design is to determine

how cursors get instantiated. We use a variation on Factory Method to

abstract the instantiation process.class Structure { public: // ... virtual Cursor* cursor () { return new ListCursor; } // ... };

Page 39: Type Laundering & Prototype Pattern Kunal Chaudhary.

Another problem But, since something of type Cursor*

is returned by cursor( ), clients can access subclass-specific operation only when they start dynamic casting in order to find out the type.

Meanwhile, structure subclasses are free to redefine cursor-manipulating operations.

Page 40: Type Laundering & Prototype Pattern Kunal Chaudhary.

Memento Comparison The following diagram illustrates type-

laundering based implementation and how it differs from implementation based in memento pattern.

Page 41: Type Laundering & Prototype Pattern Kunal Chaudhary.

Diagram

Page 42: Type Laundering & Prototype Pattern Kunal Chaudhary.

Main differences The most important difference is the

use of ConcreteMemento subclass that adds the privileged interface to the bare-bones Memento interface.

Type laundering absolves a C++ implementation from using friend and having to work around its shortcomings.

Page 43: Type Laundering & Prototype Pattern Kunal Chaudhary.

Conclusion Basically, Type laundering cleans up

your design and makes it efficient with a lot less work.