object- oriented programming part ii• allows us to substitute properly implemented objects of...
TRANSCRIPT
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
Chapter 6
Object-Oriented
ProgrammingPart II
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Preview
• issues surrounding the object creational process• the Abstract Factory design pattern• private and protected inheritance• multiple inheritance• comparison of delegation and inheritance• programming to an interface• several new design patterns:
- Prototype- Bridge- Adapter- State
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Managing the Creational Process, Part II: Abstract Factory Design Pattern
• the Instantiating Operation Idiom specified how to design classes so that you can take control over the creation of their objects
• the Singleton design pattern was designed so that at most one instance of a class may be created
• the Abstract Factory design pattern is used to manage the general creational process in the context of classes and inheritance
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Managing the Creational Process, Part II (cont.)
When a class constructor is used to create an object, it creates several dependencies: • it makes your code dependent on the objects of this particular class, • it makes it dependent on the name of the specific class used to
create it (the class name is said to be hard-coded).
Is there anything wrong with hard coding class names? It makes it difficult to modify your program, should you want to
replace some class in the program with a different class, say because the new class has a better implementation, but has the same behavior.
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Managing the Creational Process, Part II (cont.)
Consider a polynomial or a rational function represented by a string. In order to operate on the function, for example to display it:• you need to read in the string• after the string is read, you have to parse it to decide on the type of
function it represents• use it to create an object of type Polynomial or an object of
type Rational• then use its interface to perform the display operation. If you are hard coding the class used to create new objects in your
program, then whenever new function types are added, each part of the code that creates objects representing these functions has to be modified.
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Managing the Creational Process, Part II (cont.)
Solution: • encapsulate the creation of objects in another class• use the interface of this class to get new objects whenever they are
required. Any future changes to the creational process will be isolated to the class that produces objects.
Terminology:• the object being created is a product• the object that creates other objects is a factory; responsible for
producing a specific product using a factory method.
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Managing the Creational Process, Part II (cont.)
In our case of mathematical functions we have two products: • a polynomial function • a rational function
Your code would use two classes: • an abstract product class, i.e. the base class for all products, • the factory class; the factory method has a string parameter to decide
which product it should produce.
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Managing the Creational Process, Part II (cont.)
Actions:• create a factory object• use its factory method to create a specific product • use the abstract product interface to invoke the required operation
for a product; for example, to display the rational function.
The product dependency is now encapsulated in the factory class, which means that the remainder of your code is not dependent on a specific product.
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Managing the Creational Process, Part II (cont.)
To construct an object, you need to know the type of this object:• the constructor cannot be virtual• it cannot be abstract, which would allow the derived class to decide
what type of object is created.
A factory method is virtual:AbstractProduct* Factory::factoryMethod(...);
returns a product derived from the class AbstractProduct.
Also known as a virtual constructor: various classes derived from Factory, such as AnotherFactory can decide on the specific type of a product to create.
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Managing the Creational Process, Part II (cont.)
The factory method is often useful in combination with the Template Method pattern.If the template method needs to create an object, then it can use a factory method rather than hard coding class names.
Consider an abstract class Factory, which has a factory method to create products. These products are derived from an abstract class Product. • Concrete factories (classes derived from Factory) create concrete
products. • A template method templateOP() uses the factory method to return
objects of classes derived from the class Product
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Managing the Creational Process, Part II (cont.)
The client who wants to invoke the template method:• creates a concrete factory• calls the template method; this method will use a factory method to
create a product, and then use this product.
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Abstract Factory
The Abstract Factory:an abstract class with a method to return specific factories. Also has abstract factory methods to return instances of concrete derived classes of the abstract product. The user of this never creates objects directly; instead, gets a factory and asks this factory to create a concrete product.
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Abstract Factory (Example)
A system where various kinds of objects are created:• from interactive file input on a local machine• from a remote machine on the network.
The user should be able to code to the same interface:• An abstract product class with two abstract functions to open a file
for reading and writing• Two concrete product classes derived from this abstract class that
implement a local and a remote file access• a concrete factory has createAbstractProduct(string fname) to
examine fname and depending on whether it represents a local filename or a remote filename, to return the appropriate concrete product.
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Abstract Factory (Example)
Various simple file operations, such as computing the number of lines in a file can be implemented:
• without caching• with caching
We need to create two different products (instances that either do or do not cache). The responsibility of creating products will be assigned to an abstract factory method; the derived class will implement this abstract method as a function returning an instance of this class.
The function lines() is a template method that uses the factory method to create the product (which is a cached or a non-cached application), and then invokes the operation lines() from this product.
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Abstract Factory (Example)
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
Abstract Factoryclass AbstractFileOps { //abstract productpublic:
virtual long lines() const = 0; protected:
virtual ~AbstractFileOps();};
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
Abstract Factoryclass FileOps : public AbstractFileOps { // implements
public: // concrete
virtual long lines() const; // product
FileOps(const string&);~FileOps();
private:mutable ifstream fileVar_;
};
class CachedFileOps : public AbstractFileOps {public:virtual long lines() const;virtual void clearCache();CachedFileOps(const string&);~CachedFileOps();
private:mutable long lines_;mutable bool linesCached_;mutable ifstream fileVar_;
};
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
Abstract Factoryclass AbstractApplication { // abstract factorypublic:virtual AbstractFileOps* factoryMethod() const = 0;long lines() const; // template method
virtual ~AbstractApplication();};
long AbstractApplication::lines() const { AbstractFileOps* afo = factoryMethod();return afo->lines();
}
AbstractApplication::~AbstractApplication() {}
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
Abstract Factoryclass RegularApplication : public AbstractApplication { public: // concrete factory implements
RegularApplication(const string&);~RegularApplication();virtual FileOps* factoryMethod() const;
private:string filename_;
};
class CachedApplication : public AbstractApplication { public:
CachedApplication(const string&);~CachedApplication();virtual CachedFileOps* factoryMethod() const;void clearCache();
private:string filename_;
};
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
Abstract FactoryFileOps* RegularApplication::factoryMethod() const {
return new FileOps(filename_);}
RegularApplication::RegularApplication(const string& filename) : filename_(filename) {}
CachedFileOps* CachedApplication::factoryMethod() const {return new CachedFileOps(filename_);
// same kind of constructor for CachedApplication
void CachedApplication::clearCache() {CachedFileOps* cs = factoryMethod();cs->clearCache();
}
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
Abstract Factoryint main(int argc, char* argv[]) {if(argc != 3) {cerr << "usage " << argv[0] << " file1 file2" << endl;return 1;
}
AbstractApplication* aa= new CachedApplication(argv[1]);AbstractApplication* bb= new RegularApplication(argv[2]);
cout<<"lines in "<<argv[1] << " " << aa->lines() << endl;cout << "clear cache" << endl;aa->clearCache();
cout<<"lines in "<<argv[1] << " " << aa->lines() << endl;cout<<"lines in "<<argv[2] << " " << bb->lines() << endl;}
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Abstract Factory (Example)
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
Abstract Factoryclass FunctionFactory { // abstractpublic:virtual Function* createFunction(const string&) const=0;static FunctionFactory* getFactory(const string&);};
FunctionFactory* FunctionFactory::getFactory(const string& s) {
string::size_type pos = s.find_first_of('/');// if s represents a polynomial
if(pos == string::npos)return new PolynomialFactory();
return new RationalFactory();}
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
Abstract Factoryclass PolynomialFactory : public FunctionFactory {public:virtual Polynomial* createFunction(const string&) const;};
class RationalFactory : public FunctionFactory {public:virtual Rational* createFunction(const string&) const;virtual ~RationalFactory();
};
Rational* RationalFactory::createFunction(const string& s) const {
return new Rational(s);}
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Abstract Factory (Example)
An application in which you use two kinds of functions: polynomials and rational functions (quotients of two polynomials).The client of the program uses an abstract factory, FunctionFactory and an abstract product, Function.There are two concrete factories, RationalFactory and PolynomialFactory to create the concrete products Rationaland Polynomial:
string s;cin >> s;FunctionFactory* factory = FunctionFactory::getFactory(s);Function* foo = factory->createFunction(s);foo->display();
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Private Inheritance
Public inheritance:• all public features of the base class are inherited • allows us to substitute properly implemented objects of derived
classes for objects of the base class.
Private inheritance:• don’t inherit the entire interface• don’t inherit even a part of the entire interface• inherit just the implementation of the various operations. For
example, you may need to operate on data with more stringent requirements, and so may need to restrict the original interface
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Private Inheritance (cont.)
class Dequeue { public:Dequeue(int size = 10);virtual ~Dequeue();void insertL(int);void insertR(int);int removeL();int removeR();
protected:int size_;int* elem_; int left_;int right_;
};
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Private Inheritance (cont.)class Queue: private Dequeue { // note: private
public:using Dequeue::insertL; // restore insertL();
using Dequeue::removeR; // restore removeR();Queue(int size = 10);virtual ~Queue();
};
equivalent to:class Queue { //PSEUDO-CODEpublic:void insertL(int);int removeR();Queue(int size = 10);virtual ~Queue();
private:…
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Private Inheritance (cont.)class Stack : private Dequeue {// doesn't inherit the interface
public:Stack(int size = 10);~Stack();void push(int);int pop();bool full() const;
};void Stack::push(int i) {insertL(i);
}bool Stack::full() const {return left_ == right_;
}
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Private Inheritance (cont.)
Since the interface is not inherited, private inheritance does not support isA relationships:
• a Queue is not a Stack• Queue objects cannot be used where Stack objects are expected.
Private inheritance represents a is-implemented-in-terms-of relationship:
• Stack is-implemented-in-terms-of Dequeue.
In other words, private inheritance allows the derived class to reuse the code of the base class.
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Protected Inheritance Protected inheritance: • all public features of the base class become protected features of the
derived class (protected features of the base class continue to be protected in the derived class)
• useful if you do not want to finalize the derivations, that is you want to make it possible to have additional derived classes:
class Stack : protected Dequeue {public:Stack(int size = 10);~Stack();void push(int);int pop();bool full() const;
};
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Revisiting Inheritance A default implementation of a virtual function may turn out to be dangerous, because the designer of the derived class may forget to add her or his own implementation:
class Shape {public:virtual void draw() const;...
};void Shape::draw() {... // default implementation; draws a logo shape
}
class Rectangle : public Shape {
public:... // no draw() here
};
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Revisiting Inheritance
Shape* s = new Rectangle;s->draw(); // draws the logo, not the rectangle
You can force the inheriting clients to provide their own implementations, and have a default implementation in the base class:class Shape { // abstractpublic:virtual void draw() const = 0;...
};void Shape::draw() {// default implementation; draws a logo shape
...}
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Revisiting Inheritance
class Rectangle : public Shape { // still abstractpublic:... // no implementation of draw()
};
Shape* s = new Rectangle;s->draw(); // Rectangle is abstract
The base class default implementation of draw() can be used to implement the derived implementation:
void Rectangle::draw() {Shape::draw(); // default implementation... // specific for Rectangle
}
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
To provide a default implementation that must be redefined in a derived class, use pure virtual operations and provide their implementation.
Default Implementation
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Inheritance versus Delegation
• white-box reuse through inheritance. Internals of the parent classes are visible to the derived classes. Uses a compile-time relationship between two classes (a base class and a derived class) and you cannot make modifications at run-time.
• black-box reuse through delegation. Internal details of the objects are not visible. Uses a runtime-time relationship between two objects.
white-box black-box
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Inheritance versus Delegation (cont.)
-The handle represents an abstraction, and is visible to the client-The invisible body provides the implementation.-Object composition combined with inheritance is often a better alternative than just inheritance:• the client programs according to an interface provided by a class (the
handle) whose object delegates requests to the object providing the implementation (the body).
• the client's code only has to be relinked with the modified code• decomposes an abstraction into smaller, more manageable parts• helps the programmer to define additional functionality for the
implementation without affecting the client; e.g. support for the sharing of objects by using reference counting
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Multiple Inheritance, Part I C++ Comments about C++
class CE : public Ifc {
public derivation to implement abstract interface
class Ifc : public Ifc1, public Ifc2 {
public derivation to extend abstract interfaces of several classes
class CE : public C {
public derivation to inherit an interface
class CE : public C, public Ifc {
public derivation to implement abstract interface and derived class
class CE : private C, public Ifc {
public derivation from the interface and private derivation from the class (mixin class).
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Programming to an Interface
One of the important goals in writing good code is reusability:minimize the dependencies between subsystems
Program to an interface, not an implementation
• access objects in terms of their abstract interfaces, that is interfaces consisting entirely of abstract operations
• do not use concrete operations because this requires binding to a specific implementation.
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Decoupling Interfaces and Implementations
The Account class is abstract; there may be various derived classes, such as SavingsAccount, which implement Account. The handle class Bank does not need to be changed when new derived classes are used.
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: The Bridge design pattern
Using inheritance to provide implementations of a single abstraction:• tightly binds these implementations to the abstraction• makes it difficult to update the client's code, and reuse the abstraction.
In C++, the complete class definition, including the private and protected sections, is needed in order to compile the client's code• leads to a tight coupling between the abstraction and its
implementations• makes modifications more difficult.
The Bridge Design Pattern – a structural patternseparates and decouples the abstraction and the implementation
Skip Bridge
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: The Bridge design pattern (cont.)
There are two independent class hierarchies bridged through a delegate. Implementation details are hidden from the clients, who access only the abstraction. Both the abstraction and the implementation classes can be extended independently.
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Reference Counting
You can use the Bridge Design Pattern to share objects and use reference counting to deallocate them when they are no longer used:• have the counters in the body• have the copying operations in the handle.
These copying operations could include dealing with things like object assignments:• incrementing the reference counter of the right hand side• decrementing the reference counter of the left hand side
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Reference Counting (cont.)class Point { public:Point(double = 0, double = 0);virtual ~Point(); double getX() const;double getY() const;
private:double x_;double y_;
};
To add reference counters to Point objects, we need to create a new class, here called PointCounted, which is used by the clients. Therefore, this PointCounted class is the handle, while the class Pointis the body.
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Reference Counting (cont.)class PointCounted {public:PointCounted(double = 0, double = 0); //creates a point PointCounted(const PointCounted&);PointCounted(const Point&); PointCounted& operator=(const PointCounted&);~PointCounted();double getX() const;double getY() const;
private:Point* p_;int* count_;
};
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
PointCountedPointCounted::PointCounted(double x, double y) {
p_ = new Point(x, y);
count_ = new int(1);
}
PointCounted::PointCounted(const Point& pp) {
p_ = new Point(pp);
count_ = new int(1);
}
PointCounted::~PointCounted() {
--(*count_); // one fewer reference
if (*count == 0) // garbage
{ delete p_; delete count_; }
}
double PointCounted::getX() const {
return p_->getX(); // same for Y
}
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
PointCountedPointCounted::PointCounted(const PointCounted& pc) {
count_ = pc.count_;
p_ = pc.p_;
++(*count_);
}
PointCounted& PointCounted::operator=(const PointCounted& pc) {
if(this == &pc) return *this;
++(*pc.count_); // RHS has one more reference
--(*count_); // LHS has one less reference
if(*count_ == 0) { // garbage
delete p_;
delete count_;
}
count_ = pc.count_;
p_ = pc.p_;
return *this;
}
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Reference Counting (cont.)PointCounted p1(1, 3);if(...) { PointCounted p2(p1); // share the same pointcout << p1.getX() << " " << p2.getY() << endl;
} // now there is only one copyPointCounted p2(14, 4); p1 = p2; // one copy is collected
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
To avoid the need for unnecessary recompilation of the client's code, separate the interface and the implementation, and include only those header files that are absolutely necessary.
Avoiding Recompilation
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Creating and Copying Abstract Interfaces: Prototype Design Pattern
The cloning operation has its roots in yet another creational design pattern:
the Prototype design pattern gives a flexible alternative to inheritance. The client class creates a prototype object; when this client again needs to create a new object, it asks the prototype object to clone itself. Therefore, objects that are used as prototypes must support the clone() operation, in addition to their own operations
Skip Prototype
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Creating and Copying Abstract Interfaces: Prototype Design Pattern (cont.)
Application of the Prototype design pattern:the creation and copying of an abstract interface.
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
Accountclass Account { // abstract prototypepublic:virtual void open() = 0;virtual void withdraw(double) = 0;virtual void deposit(double) = 0;virtual Account* clone() const = 0;virtual Account* create() const = 0;
};class SavingsAccount : public Account { // implementspublic:virtual void open();virtual void withdraw(double);virtual void deposit(double);virtual SavingsAccount* clone() const; virtual SavingsAccount* create() const;
protected:...
};
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
AccountSavingsAccount* SavingsAccount::clone() const {return new SavingsAccount(*this);
};SavingsAccount* SavingsAccount::create() const {return new SavingsAccount();
};
The variable prot is assumed to point to the prototype account:Account* a = prot->clone();
If the value of the prot is an object of the class SavingsAccount, thenclone() returns an object of the same class (polymorphism).
How do we create the initial prototype?
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
Accountclass BankFactory {public:BankFactory(Account*);virtual Account* makeAccount() const;
private:Account* accPrototype_;
};BankFactory::BankFactory(const Account* a) {accPrototype_ = a;
}
To configure a factory for a particular type of account:BankFactory saving(new SavingsAccount());
The client of BankFactory can use its operation makeAccount() to clone the prototype:Account* BankFactory::makeAccount() const {return accPrototype_->clone();
}
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
AccountNow, let's look at the client code:
Account* sa = saving.makeAccount();
Account* sa1 = sa->clone();//clone existing saving accountAccount* sa2 = sa->create(); // create new saving account
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Creating and Copying Abstract Interfaces: Prototype Design Pattern (cont.)
-delegate_:Account*
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Modifying Existing Interfaces: Adapter Design Pattern
Consider a class, called Adaptee with a given interface, and an application that needs almost exactly this kind of an interface, but with some minor differences.
Modifying the class interface is not necessarily a feasible solution; it would really be useful to adapt the existing Adaptee to the needs at hand.
The Adapter Design Pattern can help us to accomplish precisely this. The pattern is an example of a structural pattern:
how to compose existing objects and classes to form new structures.
Skip Adapter
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Modifying Existing Interfaces: Adapter Design Pattern (cont.)
Class adapters: use mixins to inherit and implement the interface of TargetIfc and to inherit only the implementation of Adaptee
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Modifying Existing Interfaces: Adapter Design Pattern (cont.)
Object adapters: use object composition to delegate requests to Adaptee
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
Adapterclass DictionaryNamespace::DictionaryIfc { // abstract
public:virtual void insert(const string&) = 0; virtual void remove(const string&) = 0;virtual bool member(const string&) const = 0;
};class OldStuffNamespace::Dictionary { // existing
public:void insert(const char* const); void remove(const char* const);bool member(const char* const) const;
private:... // not shown here
};
In order to implement DictionaryNamespace::DictionaryIfc
an adapter mixin class ClassDictionaryAdapter
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
Adapterclass DictionaryNamespace::ClassDictionaryAdapter : public DictionaryNamespace::DictionaryIfc // implementsprivate OldStuffNamespace::Dictionary { // inherit impl.
public:virtual void insert(const string&); virtual void remove(const string&);virtual bool member(const string&) const;
};
void DictionaryNamespace::DictionaryAdapter insert(const string& s) {OldStuffNamespace::Dictionary::insert(s.c_str());
}
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Self-modifying Interfaces: State Design Pattern
The State pattern is useful if an object may be in a large number of states, and the behavior of this object changes at run-time whenever its state changes.
Rather than coding the behavior using a large switch statement, this behavior is implemented by the subclasses of the state.
Skip State
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Self-modifying Interfaces: State Design Pattern (cont.)
The client of the State Design Pattern communicates with a class called Context. This design pattern also includes an abstract class called the State; concrete states implement this class’s behavior.
C++ Programming with Design Patterns Revealed Tomasz Müldner Copyright: Addison-Wesley Publishing Company, 2002
6: Self-modifying Interfaces: State Design Pattern (cont.)
An example of an application of the State design pattern:TCP connections where a TCP object may be in several states, such as:• Established • Closed• Listening. When a TCP connection object receives a request, its response depends
on its state.For example, the action taken for an Open request depends on whether
the current state is Established or Closed.