Where Do Surrogates Fit into ThisProxy PatternObserver PatternVisitor PatternByKurt Rehwinkel
Where Do Surrogates Fit into This
Introduction – What is a surrogate?
Webster’s Dictionary defines it as “one appointed to act in place ofanother”. The general context is that of a lawyer who represents aclient before a court.
A more general concept is to consider a surrogate as someone orsomething that performs a process or task that is unable orunwilling to be performed by another.
Garbage collector, postal service, etc.
From the software perspective, surrogates can be thought of as“helper” type classes. These patterns provide valuable services byallowing aspects of a design to vary based on the needs of thesoftware. These varying aspects include such things as interfaces,implementations, structures, responsibilities, etc. (Patterns 30)
Where Do Surrogates Fit into This
Things to consider when selecting Surrogates:
The requirements of the design may be such thatmultiple surrogate patterns should be implemented toobtain the cleanest design solution. In the file systemexample, the COMPOSITE pattern served as a solutionwhen considering files and folders/directories. However,the PROXY served as a better solution whenimplementing symbolic links.
One or more additional surrogate patterns may berequired in the implementation in support of thesoftware design. In the file system example, theOBSERVER pattern was used to notify all proxies when afile was deleted to prevent “dangling” pointers.
Where Do Surrogates Fit into This
Working with base classes:
As a design evolves and the implementation develops,there is a tendency to treat a base class as a dumpingground for additional capability. This results in baseclasses that are tough to understand, cumbersomemaintain, and difficult to implement.
The author makes the assertion that a primary goal inthe design of bases classes is to provide a minimal set ofoperations allowing open-ended functionality.
If you find yourself adding functionality to a base class tosupport a single subclass, perhaps a pattern is adesirable alternative.
Where Do Surrogates Fit into This
Using multiple surrogate patterns:
Some designs may result in multiple patterns beingimplemented in classes that are interdependent.
These associations are result in “dense” composition ofpatterns. Having dense compositions can result in“profound” code (good stuff in a small space).
However, care must be taken to ensure that the desiredpatterns do not get lost after implemented.
Where Do Surrogates Fit into This
Reviewing surrogate usage:
Before adding functionality to base classes in the designsoftware, consider surrogate patterns as a betteralternative.
Use multiple surrogate patterns as needed to support thesoftware design. This can serve to generate significantcode in a small space.
Be careful to ensure that software patterns do not getlost after it has been implemented (can happen in“dense” composition patterns).
Proxy Pattern
Intent
Provide a surrogate or placeholder for another object tocontrol access to it
Other Names
Surrogate
Proxy Pattern: Applicability
Forms of the proxy pattern:
Remote proxy – Provides a local representative for anobject in a different address space.
Virtual Proxy – Creates expensive objects on demand.
Protection Proxy – Controls access to the original object.
Smart References – Additional functionality pointers.
Smart Pointers
Initial loading of persistent objects.
Object locking.
Proxy Pattern: Participants
Proxy
Maintains a reference to the real subject.
Provide identical interface to Subject so the Proxy can besubstituted.
Controls access to the real subject and may be responsible forcreating and deleting the real subject.
RealSubject
Defines the real object that the proxy represents.
Subject
Defines the common interface for RealSubject and Proxy so that theproxy to be used wherever a RealSubject is expected.
Proxy Pattern: Structure
Proxy Pattern: Example
class Image;
class ImagePtr {
public:
ImagePtr(const char* file);
virtual ~ImagePtr();
virtual Image* operator->();
virtual Image& operator*();
private:
Image*_image;
const char* _file;
Image* LoadImage();
};
Image* ImagePtr::LoadImage(){
If (_image == 0 ) {
_image = LoadAnImageFile(_file);
}
return _image;
}
Image* ImagePtr::operator->() {
return LoadImage();
}
Image& ImagePtr::operator*(){
return *LoadImage();
}
To implement the Real Subject methods:
ImagePtr image = ImagePtr(“aFile”);
image->Draw(Point(50,100));
//(image.operator->())->Draw(Point(50,100))
Proxy Pattern: Consequences
Each proxy introduces a level of indirection. Thismay result in hiding detail from the implementer.
A remote Proxy can hide the fact that object resides in adifferent address space.
A Virtual Proxy can perform optimizations such ascreation on demand.
Protection Proxy and Smart References can allowadditional housekeeping tasks when object is accessed.
Copy-On-Write
This hides optimization in which an object is not copieduntil it’s attributes are modified.
Proxy: Related Patterns
Adapter
Provides a different interface to an object. Since a proxymay deny request based on access, the interface is willbe a subset.
Decorator
Similar implementation to proxy but has a differentpurpose.  This adds responsibilities to an object ratherthan controlling access.
Observer Pattern
Intent
Define a one-to-many dependency between objects sothat when one object changes state, all its dependentsare notified and updated automatically
Also Known As
Dependents
Publish-Subscribe
Observer Pattern: Motivation
Partitioning a system into a collection ofcooperating classes results in a need to maintainconsistency between objects.
It is undesirable to achieve consistency via tightlycoupled dependencies as this limits reusabiltiy.
Observer Pattern: Applicability
The following situations are prime examples forimplementation of the observer pattern.
When an abstraction has two aspects with onedependant on the other.
When a change to one object requires changes to one ormore other objects.
When an object needs to notify other objects but remainloosely coupled.
Observer Pattern: Participants
Subject
Maintains knowledge of the Observers.
Defines an interface for attaching and detachingObserver objects.
Observer
Defines an interface for objects to be notified when asubject changes.
Observer Pattern: Participants
ConcreteSubject
Maintains the state Subject.
Notifies the Observers via the Subject when its statechanges.
ConcreteObserver
Maintains a reference to the ConcreteSubject.
Stores state that should stay consistent with thesubject’s.
Implements the updating interface.
Observer Pattern: Structure
Observer Pattern: Collaborations
Observer Pattern: Consequences
Abstract coupling between Subject and Observer.
Support for broadcast (multicast) communication.
Unexpected updates caused by cascading updatesto observers and their dependant objects.
Observer: Implementation
Mapping subjects to their observers.
Local storage is fast but may consume memory.Associative mapping saves space but requires is slower.
Observing multiple subjects by extending theupdate method in the Observer.
Who triggered the update?
The state-setting operations in the Subject determinewhen the notification occurs.
The client(s) are responsible for determining theappropriate time to notifiy.
Observer: Implementation
Dangling references to deleted subjects.
Subjects must notify Observers of the intent to bedeleted.
Ensuring Subject state is “self-consistent” beforenotification.
Avoiding observer-specific update protocols.
Push Model – Information delivered as part of thenotification.
Pull Model – Observers ask for details in response to thenotification.
Observer: Implementation
Specifying modifications of interest explicitly.
State information is classified into “aspects” which are identifiedduring notification.
Encapsulating complex update semantics through theimplementation of a “Change-Manager”.
Takes responsibility of maintaining references to observers awayfrom the Subject.
Defines a particular update strategy.
Updates all dependent observers at the request of a subject.
Combining the Subject and Observer.
May be useful when multiple inheritance not supported by language,both interfaces may reside in one class.
Observer: Related Patterns
Mediator
The ChangeManager encapsulates complex updatesemantics, thus acting as a mediator between theSubject and its Observers.
Singleton
ChangeManager may be unique and globally accessible.
Visitor Pattern
Intent
Lets you define a new operation without changing theclasses on which they operate.
Motivation
Allows for increased functionality of a class(es) whilestreamlining base classes. As stated in the generalsection concerning surrogates, the author asserts that aprimary goal of designs should be to ensure that baseclasses maintain a minimal set of operations.
Encapsulates common functionality in a class framework.
Visitor Pattern
Motivation (cont)
Visitors avoid type casting that is required by methodsthat pass base class pointers as arguments. Thefollowing code describes how a typical class couldexpand the functionality of an existing composite.
Void MyAddition::execute( Base* basePtr) {
   if( dynamic_cast<ChildA*>(basePtr)){
      // Perform task for child type A.
   } else if ( dynamic_cast<ChildB*>(basePtr)){
      // Perform task for child type B.
   } else if( dynamic_cast<ChildC*>(basePtr)){
      // Perform task for child type C.
   }
}
Visitor Pattern: Applicability
The following situations are prime examples forimplementation of the visitor pattern.
When an object structure contains many classes ofobjects with different interfaces and you want to performfunctions on these objects that depend on their concreteclasses.
When you want to keep related operations together bydefining them in one class.
When the class structure rarely change but you need todefine new operations on the structure.
Visitor Pattern: Participants
Visitor
Declares a Visit Operation for each class of ConcreteElements in the object structure.
Concrete Visitor
Implements each operation declared by Visitor.
Element
Defines an Accept operation that takes the visitor as anargument.
Visitor Pattern: Participants
Concrete Element
Implements an accept operation that takes the visitor asan argument.
Object Structure
Can enumerate its elements.
May provide a high level interface to all the visitor to visitits elements.
May either be a composite or a collection.
Visitor Pattern: Structure
VisitorParticipants
Visitor Pattern: Collaborations
VisitorCollaborations
Visitor Pattern: Consequences
Makes adding new operations easier.
Collects related functionality.
Adding new Concrete Element classes is difficult.
Can “visit” across class types, unlike iterators.
Accumulates states as they visit elements.
May require breaking object encapsulation tosupport the implementation.
Visitor: Implementation
Implementation by the element classes.
The base element class contains an abstract method toaccept the visitor.
Virtual void accept(Visitor&) = 0;
The concrete element classes implement the accept callin an identical manner.
void ElementA::accept(Visitor& v) {v.visit(this);}
void ElementB::accept(Visitor& v) {v.visit(this);}
Visitor: Implementation
Implementation of a single Visitor class can beused to implement simpler functionality.
A single visitor class may contain the set of methods forimplementing all concrete element types.
void visit(ElementA*) ;
The client implements the single visitor and be passedinto any element pointer type call.
Visitor v;
anElementPtr->visit(v);
Visitor: Implementation
Implementation of functionality for multiple visitortypes is easy through inheritance.
A base visitor class contains an abstract method as aplaceholder for each concrete element.
void visit(Element*)=0 ;
Each concrete visitor implements the functionality for allconcrete elements.
void VisitorTypeA::visit(ElementA*) ;
void VisitorTypeA::visit(ElementB*) ;
void VisitorTypeB::visit(ElementA*);
void VisitorTypeB::visit(ElementB*);
Visitor: Implementation
The client implements the a instance of EACH visitor typepasses into any element pointer type call.
VisitorTypeA vA; VisitorTypeB vB;
anElementPtr->visit(vA);
anElementPtr->visit(vB);
Visitor: Related Patterns
Composites
Visitors can be used to apply an operation over an objectstructure defined by the composite pattern.
Interpreter
Visitors may be applied to do the interpretation.