??xml version="1.0" encoding="utf-8" standalone="yes"?>
Part of the red marker to add by YeHaoQOrder oneself to better understand.
观察者模?设计模式
来自于《大话设计模式?br>观察者模式:定义了一U一对多的依赖关p,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生时Q会通知所有观察者对象,使他们自动更新自己?br>
行ؓ型模式?br>
UML cdQ?br>
代码实现 C++Q?br>
2 #include <string>
3 #include <list>
4 #include <algorithm>
5 using namespace std;
6
7 class Subject;
8
9 class Observer //观察?/span>
10 {
11 protected:
12 string name;
13 Subject* sub;
14 public:
15 Observer(const string& n, Subject* s) : name(n), sub(s) {}
16 virtual void Update() = 0;
17 };
18
19 class Subject //被观察?br> 20 {
21 protected:
22 list<Observer*> observers;
23 string action;
24 public:
25 virtual void Attach(Observer* ob) = 0; //增加观察者对?br> 26 virtual void Detach(Observer* ob) = 0; //U除观察者对?br> 27 virtual void Notify() = 0;
28 virtual void setAction(const string& s) = 0;
29 virtual string getAction() = 0;
30 };
31
32 class StockObserver : public Observer
33 {
34 public:
35 StockObserver(const string& name, Subject* s) : Observer(name, s) {}
36 virtual void Update()
37 {
38 cout << sub->getAction() << '\t' << name << " 关闭股票行情Ql工作!" << endl;
39 }
40 };
41
42 class NBAObserver : public Observer
43 {
44 public:
45 NBAObserver(const string& name, Subject* s) : Observer(name, s) {}
46 virtual void Update()
47 {
48 cout << sub->getAction() << '\t' << name << " 关闭 NBAQl工作!" << endl;
49 }
50 };
51
52 class Boss : public Subject
53 {
54 //private:
55 // list<Observer*> observers;
56 // string action;
57 public:
58 virtual void Attach(Observer* ob)
59 {
60 observers.push_back(ob);
61 }
62 virtual void Detach(Observer* ob)
63 {
64 list<Observer*>::iterator iter= find(observers.begin(), observers.end(), ob);
65 if (iter != observers.end())
66 {
67 observers.erase(iter);
68 }
69 }
70 virtual void Notify()
71 {
72 for (list<Observer*>::iterator iter = observers.begin(); iter != observers.end(); ++iter)
73 {
74 (*iter)->Update();
75 }
76 }
77 virtual void setAction(const string& s)
78 {
79 action = s;
80 }
81 virtual string getAction()
82 {
83 return action;
84 }
85 };
86
87 class Secretary : public Subject
88 {
89 //private:
90 // list<Observer*> observers;
91 // string action;
92 public:
93 virtual void Attach(Observer* ob)
94 {
95 observers.push_back(ob);
96 }
97 virtual void Detach(Observer* ob)
98 {
99 list<Observer*>::iterator iter = find(observers.begin(), observers.end(), ob);
100 if (iter != observers.end())
101 {
102 observers.erase(iter);
103 }
104 }
105 virtual void Notify()
106 {
107 for (list<Observer*>::iterator iter = observers.begin(); iter != observers.end(); ++iter)
108 {
109 (*iter)->Update();
110 }
111 }
112 virtual void setAction(const string& s)
113 {
114 action = s;
115 }
116 virtual string getAction()
117 {
118 return action;
119 }
120 };
121
122
123
124 int main()
125 {
126 Boss* huhansan = new Boss;
127 StockObserver* so = new StockObserver("abc", huhansan);
128 NBAObserver* no = new NBAObserver("xyz", huhansan);
129
130 huhansan->Attach(so);
131 huhansan->Attach(no);
132 huhansan->setAction("我胡汉三又回来了Q?/span>");
133 huhansan->Notify();
134
135 huhansan->Detach(no);
136 huhansan->setAction("开会!");
137 huhansan->Notify();
138
139 delete huhansan;
140
141 Secretary* s = new Secretary;
142 s->Attach(no);
143 s->Attach(so);
144 s->setAction("老板来了Q?/span>");
145 cout << s->getAction() << endl;
146 s->Notify();
147
148 delete so;
149 delete no;
150 delete s;
151
152 return 0;
153 }
]]>
一、功?/strong>
一个类的接口{换成客户希望的另外一个接口,解决两个已有接口之间不匹配的问题。Adapter模式使得原本׃接口不兼容而不能一起工作的那些cd以一起工作?
二、结构图
(1)class adapter
(2)object adapter
三、实?/p>
和其他很多模式一P学习设计模式的重Ҏ学习每种模式的思想Q而不应拘泥于它的某种具体l构囑֒实现。因为模式是灉|的,其实现可以是千变万化的,只是所谓万变不d宗?在STL中大量运用了Adapter模式Q象function adapter、iterator adpterQ它们与q里说的adapterl构q不一P但思想是一L。具体的介绍可到侯捷|站上找相关文章Q他讲得非常好?
四、示例代?/p>
(1)class adapter
namespace DesignPattern_Adapter
{
// class Adaptee
class Adaptee
{
public:
void SpecialRequest() {}
} ;
// class Target
class Target
{
public:
virtual void Request() = 0 ;
} ;
// class Adapter
class Adapter : public Target, private Adaptee
{
public:
virtual void Request() { SpecialRequest() ; }
} ;
}
客户端代码:
{
using namespace DesignPattern_Adapter ;
Target *p = new Adapter() ;
p->Request() ; //实际上调用的是Adaptee::SpecialRequest()
}
(2)object adapter namespace DesignPattern_Adapter
{
// class Adaptee
class Adaptee
{
public:
void SpecialRequest() {}
} ;
// class Target
class Target
{
public:
virtual void Request() = 0 ;
} ;
// class Adapter
class Adapter : public Target
{
public:
virtual void Request() { _adaptee.SpecialRequest() ; }
private:
Adaptee _adaptee ;
} ;
}
客户端代码:
{
using namespace DesignPattern_Adapter ;
Target *p = new Adapter() ;
p->Request() ; //实际上调用的是Adaptee::SpecialRequest()
}
六、实?/p>
(1)STL中的Class Adapter
STL中的Adapter Class包括Qa.stack(对应的adaptee是deque)。b.queue(对应的adaptee是deque)。c.priority_queue(对应的adaptee是vector)?下面是从VC中的< stack >拷出的stack的类定义Q?
templateclass _Container = deque<_Ty> >
class stack
{ // LIFO queue implemented with a container
public:
typedef _Container container_type;
typedef typename _Container::value_type value_type;
typedef typename _Container::size_type size_type;
stack()
: c()
{ // construct with empty container
}
explicit stack(const _Container& _Cont)
: c(_Cont)
{ // construct by copying specified container
}
bool empty() const
{ // test if stack is empty
return (c.empty());
}
size_type size() const
{ // test length of stack
return (c.size());
}
value_type& top()
{ // return last element of mutable stack
return (c.back());
}
const value_type& top() const
{ // return last element of nonmutable stack
return (c.back());
}
void push(const value_type& _Val)
{ // insert element at end
c.push_back(_Val);
}
void pop()
{ // erase last element
c.pop_back();
}
bool _Eq(const stack<_Ty, _Container>& _Right) const
{ // test for stack equality
return (c == _Right.c);
}
bool _Lt(const stack<_Ty, _Container>& _Right) const
{ // test if this < _Right for stacks
return (c < _Right.c);
}
protected:
_Container c; // the underlying container
};
关键之处在于_Container cQstack所有的操作都{交给cd理了?q实际上是前面所说的"object adapter"Q注意STL中的class adapter与上面所说的class adapter概念不完全一?
stack的用方法很单,如下Q?
{
int ia[] = { 1,3,2,4 };
deque id(ia, ia+4);
stack is(id);
}
(2)q日看了一文?#8220;Generic< Programming >Q简化异常安全代?#8221;Q原文出?a C++ ViewW???文章l对一,作者给出的代码中也使用了Adaptor模式Q也有一定代表性。我其问题一般化Q概括出以下CZQ?
问题Q假设有几个已有c,他们有某些共同的行ؓQ但它们彼此间是独立?没有共同的基c?。如Q?
class T1
{
public:
void Proc() {}
} ;
class T2
{
public:
void Proc() {}
} ;
// ...
如何以统一的方式去调用q些行ؓ呢?
解决Ҏ1Q很自然的会惛_用模板,如:
template <class T>
void Test(T t)
{
t.Proc() ;
}
的确不错Q但q只适用于简单的情况Q有时情冉|很复杂的Q比如我们无法把cd攑ֈ模板参数中!
解决Ҏ2Q困难来自于q些cL有共同的基类Q所以我们就创造一个基c,然后再Adapt?
// class IAdaptorQ抽象基c?br>class IAdaptor
{
public:
virtual void Proc() = 0 ;
} ;
// class Adaptor
template <class T>
class Adaptor : public IAdaptor, private T //实现l承
{
public:
virtual void Proc() { T::Proc() ; }
} ;
// 以统一方式调用函数ProcQ而不兛_是T1、T2或其他什么类
void Test(const std::auto_ptr& sp)
{
sp->Proc() ;
}
客户端代码:
Test(std::auto_ptr(new Adaptor)) ;
Test(std::auto_ptr(new Adaptor)) ;
上例很简单,用方法一中的模板函数可以很好地解决了。下面是一个略微复杂一点的例子Q根据参数类型来创徏适当的对象:
class T1
{
public:
T1(int) { /*...*/ }
void Proc() { /*...*/ }
} ;
class T2
{
public:
T2(char) { /*...*/ }
void Proc() { /*...*/ }
} ;
// class IAdaptorQ抽象基c?br>class IAdaptor
{
public:
virtual void Proc() = 0 ;
} ;
// class Adaptor
template
class Adaptor : public IAdaptor, private T //实现l承
{
public:
Adaptor(int n) : T(n) {}
Adaptor(char c) : T(c) {}
virtual void Proc() { T::Proc() ; }
} ;
class Test
{
public:
Test(int n) : sp(new Adaptor(n)) {}
Test(char c) : sp(new Adaptor(c)) {}
void Proc() { sp->Proc() ; }
private:
std::auto_ptr sp ;
} ;
客户端代码:
Test t1(10) ;
t1.Proc() ;
Test t2('c') ;
t2.Proc() ;
上面是示例而非实例Q你也许更愿意看看它实际的运用。去下蝲作者所写的代码Q好好欣赏一下吧?br>
C++设计模式之Abstract Factory |
2002-07-23· · ··COM集中?br> |
一、功?/strong> 提供一个创Zpd相关或相互依赖对象的接口Q而无需指定它们具体的类? 二、结构图 cd最基本的结构示意图如下Q? 在实际应用中Q类厂模式可以扩充到很复杂的情况Q如下图所C: |
优点Q?1)装创徏q程。客户不用知道类厂是如何创徏cd例的Q类厂封闭了所有创建的l节。这样可选择不同的创建方法,增加了灵zL?(2)客户与具体c隔,提高了各自的可重用性?
~点QFactorycdơ与具体cdơ通常是^行的(即一一对应?。增加一个具体类Q一般也要相应地增加一个factoryc,增加了系l复杂度?
四、实?/p>
(1)Abstract FactorycM通常是一lFactory Method的集合。个ZFactory Method模式没有本质区别?
(2)通常可以把工厂作为单件?
五、示例代?/p>
namespace DesignPattern_AbstractFactory
{
class AbstractProductA {}; // Product A
class ProductA1 : public AbstractProductA {};
class ProductA2 : public AbstractProductA {};
class AbstractProductB {}; // Product B
class ProductB1 : public AbstractProductB {};
class ProductB2 : public AbstractProductB {};
class AbstractFactory
{
public:
virtual AbstractProductA* CreateProductA() = 0 ;// 创徏ProductA
virtual AbstractProductB* CreateProductB() = 0 ;// 创徏ProductB
} ;
class ConcreteFactory1 : public AbstractFactory
{
public:
virtual AbstractProductA* CreateProductA() { return new ProductA1() ; }
virtual AbstractProductB* CreateProductB() { return new ProductB1() ; }
static ConcreteFactory1* Instance() { static ConcreteFactory1 instance ; return &instance ; }
protected:
ConcreteFactory1() {}
private:
ConcreteFactory1(const ConcreteFactory1&) ;
ConcreteFactory1& operator=(const ConcreteFactory1&) ;
} ;
class ConcreteFactory2 : public AbstractFactory
{
public:
virtual AbstractProductA* CreateProductA() { return new ProductA2() ; }
virtual AbstractProductB* CreateProductB() { return new ProductB2() ; }
static ConcreteFactory2* Instance() { static ConcreteFactory2 instance ; return &instance ; }
protected:
ConcreteFactory2() {}
private:
ConcreteFactory2(const ConcreteFactory2&) ;
ConcreteFactory2& operator=(const ConcreteFactory2&) ;
} ;
}
客户端代码:
{
using namespace DesignPattern_AbstractFactory ;
// W一U创建方?/p>
AbstractFactory *pFactory = ConcreteFactory1::Instance() ;
AbstractProductA *pProductA = pFactory->CreateProductA() ;
AbstractProductB *pProductB = pFactory->CreateProductB() ;
// W二U创建方?br> pFactory = ConcreteFactory2::Instance() ;
pProductA = pFactory->CreateProductA() ;
pProductB = pFactory->CreateProductB() ;
}
六、实?/p>
最早知道类厂的概念是在COM中,但当时也没想到这是如此重要的一U模式,在许多其他模式中都可以用到类厂模式?COM中不能直接创建组Ӟq也是由COM的一个特性决定的Q即客户不知道要创徏的组件的cd?/p>
C++设计模式之Singleton |
2002-07-26· · ··COM集中? |
一、功?
保证一个类仅有一个实例? |
Singleton模式是做?全局变量"的替代品出现的。所以它h全局变量的特点:全局可见、诏I应用程序的整个生命期,它也h全局变量不具备的性质Q同cd的对象实例只可能有一个?
四、实?/p>
教科书上的Singleton定义如下Q?
class Singleton
{
public:
static Singleton* Instance() ;
protected:
Singleton() {}
private:
static Singleton *_instance ;
Singleton(const Singleton&) ;
Singleton& operator=(const Singleton&) ;
} ;
Singleton* Singleton::_instance = NULL ;
Singleton* Singleton::Instance()
{
(_instance == NULL) ? _instance = new Singleton() : 0 ; //lazy initialization
return _instance ;
}
(1)因ؓq回的是指针Qؓ防止用户调用delete函数Q可把static Singleton *_instanceQ改为在Instance()中定义static Singleton _instance。这h然更安全Q同时也hlazy initialization的特?即第一ơ访问时才创??
(2)假设需要从Singletonz子类Q而子cM需要有同样的性质Q既只能创徏一个实例。我觉得Q这很难办。根本原因在于Instance()函数不是虚函敎ͼ不具有多态的性质。一U常用方法是把Instance()函数Ud子类中,q时只能用static Singleton *_instanceQ而不能用static Singleton _instance了,除非把_instance也要Ud子类Q无论怎么做都不优雅。另一U方法是用模ѝ具体用什么方法,只能Ҏ实际情况权衡?
五、示例代?/p>
(1)没子cȝ情况
namespace DesignPattern_Singleton
{
class Singleton
{
public:
static Singleton* Instance() { static Singleton _instance ; return &_instance ; }
protected:
Singleton() {}
private:
Singleton(const Singleton&) ;
Singleton& operator=(const Singleton&) ;
} ;
}
客户端代码:
{
using namespace DesignPattern_Singleton ;
Singleton *p = Singleton::Instance() ;
......
}
(2)有子cȝ情况
Ҏ一Q?br>namespace DesignPattern_Singleton
{
// class Singleton
class Singleton
{
protected:
Singleton() {}
static Singleton *_instance ;
private:
Singleton(const Singleton&) ;
Singleton& operator=(const Singleton&) ;
} ;
Singleton* Singleton::_instance = NULL ;
// class ConcreteSingleton
class ConcreteSingleton : public Singleton
{
public:
static Singleton* Instance() ;
protected:
ConcreteSingleton() {}
} ;
Singleton* ConcreteSingleton::Instance()
{
(_instance == NULL) ? _instance = new ConcreteSingleton() : 0 ;
return _instance ;
}
}
客户端代码:
{
using namespace DesignPattern_Singleton ;
Singleton *p = ConcreteSingleton::Instance() ;
}
Ҏ二:
namespace DesignPattern_Singleton
{
// class Singleton
class Singleton
{
protected:
Singleton() {}
private:
Singleton(const Singleton&) ;
Singleton& operator=(const Singleton&) ;
} ;
// class ConcreteSingleton
class ConcreteSingleton : public Singleton
{
public:
static Singleton* Instance() { static ConcreteSingleton _instance ; return &_instance ; }
protected:
ConcreteSingleton() {}
} ;
}
客户端代码:
{
using namespace DesignPattern_Singleton ;
Singleton *p = ConcreteSingleton::Instance() ;
}
Ҏ三:
namespace DesignPattern_Singleton
{
template < class T >
class Singleton
{
public:
static T* Instance() { static T _instance ; return &_instance ; }
protected:
Singleton() {}
private:
Singleton(const Singleton &) ;
Singleton& operator=(const Singleton&) ;
} ;
class ConcreteSingleton : public Singleton< ConcreteSingleton > {} ;
}
客户端代?br>{
using namespace DesignPattern_Singleton ;
ConcreteSingleton *p = ConcreteSingleton::Instance() ;
}
C++模式开发之Bridge |
2002-07-29· · ··COM集中? |
一、功?/strong> 抽象部分与它的实现部分分离Q它们都可以独立地变化? 二、结构图 |
// class ConcreteImplementorA
class ConcreteImplementorA : public Implementor
{
public:
virtual void OperationImp() {}
} ;
// class ConcreteImplementorB
class ConcreteImplementorB : public Implementor
{
public:
virtual void OperationImp() {}
} ;
// class Abstraction
class Abstraction
{
public:
void Operation(Implementor* imp) { assert(imp) ; imp->OperationImp() ; }
} ;
}
客户端代码:
{
using namespace DesignPattern_Bridge ;
Abstraction obj ;
Implementor *impa = new ConcreteImplementorA() ;
Implementor *impb = new ConcreteImplementorB() ;
obj.Operation(impa) ; //W一U实现方?br>obj.Operation(impb) ; //W二U实现方?br>}
四、实?/p>
(1)创徏可以在X Window System和IBM的Presentation Managerpȝ中都可以使用的窗口?书上的例?
Bridge的魅力在于抽象和实现之间是松散的关系Q它们之间可以进行随意组合。如上图中,有IconWindow+XWindowImp、TransientWindow+XWindowImp、IconWindow+PMWindowImp、TransientWindow+PMWindowImp四种l合?br>
C++模式设计之Builder |
2002-07-30· · ··COM集中? |
一、功?/strong> 一个复杂对象的构徏与它的表C分,使得同样的构E可?strong>创徏不同的表C?/strong>? 二、结构图 |
namespace DesignPattern_Builder
{
class Product1 { /*...*/ } ;
class Product2 { /*...*/ } ;
// class Builder
class Builder //抽象基类
{
public:
virtual void BuilderPartA() {} //提供~省实现
virtual void BuilderPartB() {}
virtual void BuilderPartC() {}
protected:
Builder() {}
} ;
// class ConcreteBuilder1
class ConcreteBuilder1 : public Builder //创徏Product1
{
public:
ConcreteBuilder1() : _product(NULL) {}
virtual void BuilderPartA() { /*...*/ }
virtual void BuilderPartB() { /*...*/ }
virtual void BuilderPartC() { /*...*/ }
virtual Product1* GetProduct1() { return _product ; } //q回创徏的Product1对象
private:
Product1 *_product ;
} ;
// class ConcreteBuilder2
class ConcreteBuilder2 : public Builder //创徏Product2
{
public:
ConcreteBuilder2() : _product(NULL) {}
virtual void BuilderPartA() { /*...*/ }
virtual void BuilderPartB() { /*...*/ }
virtual void BuilderPartC() { /*...*/ }
virtual Product2* GetProduct2() { return _product ; } //q回创徏的Product2对象
private:
Product2 *_product ;
} ;
// class Director
class Director
{
public:
//创徏对象(Directorq不知道具体创徏出来的对象是什么样的,只有调用该函数的client知道)
void Construct(Builder *builder)
{
builder->BuilderPartA() ;
builder->BuilderPartB() ;
builder->BuilderPartC() ;
}
} ;
}
客户端代码:
{
using namespace DesignPattern_Builder ;
Director director ;
// 创徏W一U对?br>ConcreteBuilder1 *pBuilder1 = new ConcreteBuilder1() ;
director.Construct(pBuilder1) ;
Product1 *product1 = pBuilder1->GetProduct1() ;
// 创徏W二U对?br>ConcreteBuilder2 *pBuilder2 = new ConcreteBuilder2() ;
director.Construct(pBuilder2) ;
Product2 *product2 = pBuilder2->GetProduct2() ;
}
四、实?/p>
(1)例子一。如下图所C:
上图的功能是是把一个RTF文g转换为多U正文格式。RTFReaderq行语法分析Q然后将所有的token串逐一转换。可见builder是一步步地把各个部分l装Z个整体。它闭了组装的ҎQ组装出来的对象也大相径庭?br>
C++设计模式之Prototype |
2002-08-01· · ··COM集中? |
一、功?/strong> 用原型实例指定创建对象的U类Qƈ且通过拯q些原型创徏新的对象? 二、结构图 |
优点Q复制自w。客户不知道需要对象的实际cdQ只需知道它的抽象基类卛_?xl承树的情况)
~点Q必d有一个对象实?卛_?才能clone?
四、示例代?/p>
namespace DesignPattern_Prototype
{
// class Prototype
class Prototype //抽象基类
{
public:
virtual Prototype* Clone() = 0 ;
} ;
// class ConcretePrototype1
class ConcretePrototype1 : public Prototype
{
public:
virtual Prototype* Clone()
{
ConcretePrototype1 *p = new ConcretePrototype1() ;
*p = *this ; //复制对象
return p ;
}
} ;
// class ConcretePrototype2
class ConcretePrototype2 : public Prototype
{
public:
virtual Prototype* Clone()
{
ConcretePrototype2 *p = new ConcretePrototype2() ;
*p = *this ; //复制对象
return p ;
}
} ;
}
客户端代码:
{
using namespace DesignPattern_Prototype ;
ConcretePrototype1 *obj1 = new ConcretePrototype1() ;//原型对象1
ConcretePrototype2 *obj2 = new ConcretePrototype2() ;//原型对象2
Prototype *newobj1 = obj1->Clone() ;//克隆对象1
Prototype *newobj2 = obj2->Clone() ;//克隆对象2
//使用复制出的对象newobj1和newobj2
}
五、实?/p>
在一个图形编辑器中,每一个图形元素,如线、圆、文字等都应该支持拷贝操作,即点中图形,按下Ctrl+CQ再按下Ctrl+V后就会复制一个新的图形。显然这是一Uclone操作。所以在每个从Graphicz出的囑Ş子类都应q用Prototype模式Q加上Clone操作?br>
C++设计模式之Factory Method |
2002-08-05· · ··COM集中? |
一、功?/strong> 定义一个用于创建对象的接口Q让子类军_实例化哪一个类。Factory Method 使一个类的实例化延迟到其子类? 二、结构图 |
(1)在某些情况下Q比如仅仅ؓ了创建适当的Product对象而派生新的Creator子类Qƈ且创Z同Product的方法一致时Q可以考虑用模板代替ѝ如Q?
class Creator
{
public:
virtual Product* CreateProduct() = 0 ;
};
template < class ConcreteProduct >
class ConcreteCreator: public Creator
{
public:
virtual Product* CreateProduct() { return new ConcreteProduct() ; }
};
模板与承的本质区别之一是:模板Q行Z依赖于类型。承:行ؓ依赖于类型?Effective C++ Item 41) 事实上,在很多模式中都存在着可以用模板代替承的情况Q其Ҏ原因在于子cȝ行ؓ是一致的?
四、示例代?/p>
namespace DesignPattern_FactoryMethod
{
class Product { /*...*/ } ;
class ConcreteProduct : public Product { /*...*/ } ;
// class Creator
class Creator
{
public:
virtual Product* CreateProduct() = 0 ;
void Operate() ;
} ;
void Creator::Operate()
{
// ...
Product *p = CreateProduct() ;
// ...
}
// class ConcreteCreator
class ConcreteCreator : public Creator
{
public:
virtual Product* CreateProduct() { return new ConcreteProduct() ; }
} ;
}
客户端代码:
{
using namespace DesignPattern_FactoryMethod ;
ConcreteCreator p ;
p.Operate() ;
}
q里的CreateProduct其实也是一个Template Method?
五、实?/p>
Factory Method的运用太q泛了,它经常运用在其它模式中,其实例D不胜数?
(1)
MFC中的CDocumentcd包含了类g上图CApplication中的三个函数。这里的CreateDocument是一个factory methodQ因为它负责创徏一个文对象?
(2)
C++设计模式之Composite |
2002-08-06· · ··COM集中? |
一、功?/strong> 表示“部分-整体”关系Qƈ使用户以一致的方式使用单个对象和组合对象? 二、结构图 |
上图中,也可以做些扩展,Ҏ需要可以将Leaf和Composite做ؓ抽象基类Q从中派生出子类来?
三、优~点
优点Q对于Composite模式Q也思h们一开始的注意力会集中在它是如何实现组合对象的。但Composite最重要之处在于用户q不兛_是组合对象还是单个对象,用户以l一的方式进行处理,所以基cd是从单个对象和组合对象中提出的公共接口?
~点QComposite最大的问题在于不容易限制组合中的组件?
四、实?/p>
有时需要限制组合中的组Ӟ卛_望一个Composite只能有某些特定的Leaf。这个问题我是用多承和动态类型{换来解决的。假如组合对象Composite1只能包含单个对象ConcreteLeaf1QComposite2可以包含单个对象ConcreteLeaf1和ConcreteLeaf2。如下图所C:
上图中的cdơ比较多Q用了AbstractLeaf1和AbstractLeaf2Q但没用AbstractComposite1和AbstractComposite2Q这个ƈ不重要,也可以把AbstractLeaf1和AbstractLeaf2LQ这个ƈ不重要,可以Ҏ具体情况军_要不要?
单的代码实现如下Q?
namespace DesignPattern_Composite
{
class Component
{
public:
virtual void operation() = 0 ;
virtual void Add(Component*) {}
} ;
class AbstractComponent1 : virtual public Component {} ;
class AbstractLeaf1 : virtual public AbstractComponent1 {} ;
class Composite1 : public AbstractComponent1
{
public:
virtual void operation() { /* do operation */ }
virtual void Add(Component*) ;
} ;
void Composite1::Add(Component *p)
{
AbstractComponent1 *pc1 = dynamic_castQABSTRACTCOMPONENT1*Q?p) ;
if (pc1 == NULL) return ;
// do add operation
}
class AbstractComponent2 : virtual public Component {} ;
class AbstractLeaf2 : virtual public AbstractComponent2 {} ;
class Composite2 : public AbstractComponent2
{
public:
virtual void operation() { /* do operation */ }
virtual void Add(Component*) ;
} ;
void Composite2::Add(Component *p)
{
AbstractComponent2 *pc2 = dynamic_castQABSTRACTCOMPONENT2*>(p) ;
if (pc2 == NULL) return ;
// do add operation
}
class ConcreteLeaf1 : public AbstractLeaf1
{
public:
virtual void operation() { /* do operation */ }
} ;
class ConcreteLeaf2 : public AbstractLeaf1, public AbstractLeaf2
{
public:
virtual void operation() { /* do operation */ }
} ;
}
客户端代码:
?br>using namespace DesignPattern_Composite ;
Component *pc1 = new ConcreteLeaf1() ;
Component *pc2 = new ConcreteLeaf2() ;
Component *pc3 = new Composite1() ;
Component *pc4 = new Composite2() ;
pc3->Add(pc1) ; // ok
pc3->Add(pc2) ; // ok
pc3->Add(pc3) ; // ok
pc3->Add(pc4) ; // fail
pc4->Add(pc1) ; // fail
pc4->Add(pc2) ; // ok
pc4->Add(pc3) ; // fail
pc4->Add(pc4) ; // ok
}
有两炚w要注意,一是因为用了多l承Q所以需要用virtual inheritance。二是要用dynamic_cast来判断是否允许组合该lg?/p>
五、示例代?/p>
namespace DesignPattern_Composite
{
// class Component
class Component
{
public:
virtual void Operation() = 0 ;
virtual void Add(Component*) {}
} ;
// class Leaf
class Leaf : public Component
{
public:
virtual void Operation() {}
} ;
// class Composite
class Composite : public Component
{
public:
virtual void Add(Component *p) { _list.push_back(p) ; }
virtual void Operation()
{
vector< Component* >::const_iterator it ;
for (it = _list.begin(); it != _list.end(); it++)
(*it)->Operation() ;
}
private:
vector< Component* > _list ;
} ;
}
六、实?/p>
(1)JUnit中就用的是Composite模式?