青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

yehao's Blog

C++設計模式(轉載)

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/i_like_cpp/archive/2004/11/29/197760.aspx


一、功能

 

  將一個類的接口轉換成客戶希望的另外一個接口,解決兩個已有接口之間不匹配的問題。Adapter模式使得原本由于接口不兼容而不能一起工作的那些類可以一起工作。

  二、結構圖

  (1)class adapter

  (2)object adapter

三、實現

  和其他很多模式一樣,學習設計模式的重點是學習每種模式的思想,而不應拘泥于它的某種具體結構圖和實現。因為模式是靈活的,其實現可以是千變萬化的,只是所謂萬變不離其宗。 在STL中大量運用了Adapter模式,象function adapter、iterator adpter,它們與這里說的adapter結構并不一樣,但思想是一樣的。具體的介紹可到侯捷網站上找相關文章,他講得非常好。
  四、示例代碼

  (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()
}
 

  六、實例

  (1)STL中的Class Adapter

  STL中的Adapter Class包括:a.stack(對應的adaptee是deque)。b.queue(對應的adaptee是deque)。c.priority_queue(對應的adaptee是vector)。 下面是從VC中的< stack >拷出的stack的類定義:

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 c,stack所有的操作都轉交給c去處理了。(這實際上就是前面所說的"object adapter",注意STL中的class adapter與上面所說的class adapter概念不完全一致)
stack的使用方法很簡單,如下:

 

{
int ia[] = { 1,3,2,4 };
deque id(ia, ia+4);
stack is(id);
}

  (2)近日看了一篇文章“Generic< Programming >:簡化異常安全代碼”,原文出自http://www.cuj.com/experts/1812/alexandr.htm?topic=experts, 中文譯文出自"C++ View第5期"。 文章絕對一流,作者給出的代碼中也使用了Adaptor模式,也有一定代表性。我將其問題一般化,概括出以下示例:

  問題:假設有幾個已有類,他們有某些共同的行為,但它們彼此間是獨立的(沒有共同的基類)。如:

class T1
{
public:
void Proc() {}
} ;

class T2
{
public:
void Proc() {}
} ;

// ...
 


  如何以統一的方式去調用這些行為呢?

  解決方法1:很自然的會想到用模板,如:

template <class T>
void Test(T t)
{
t.Proc() ;


  的確不錯,但這只適用于簡單的情況,有時情況是很復雜的,比如我們無法把類型放到模板參數中!

  解決方法2:困難來自于這些類沒有共同的基類,所以我們就創造一個基類,然后再Adapt。

// class IAdaptor,抽象基類
class IAdaptor
{
public:
virtual void Proc() = 0 ;
} ;
// class Adaptor
template <class T>
class Adaptor : public IAdaptor, private T //實現繼承
{
public:
virtual void Proc() { T::Proc() ; }
} ;
// 以統一方式調用函數Proc,而不關心是T1、T2或其他什么類
void Test(const std::auto_ptr& sp)
{
sp->Proc() ;
}
客戶端代碼:
Test(std::auto_ptr(new Adaptor)) ;
Test(std::auto_ptr(new Adaptor)) ; 


  上例很簡單,用方法一中的模板函數就可以很好地解決了。下面是一個略微復雜一點的例子,根據參數類型來創建適當的對象:

 

class T1
{
public:
T1(int) { /*...*/ }
void Proc() { /*...*/ }
} ;

class T2
{
public:
T2(char) { /*...*/ }
void Proc() { /*...*/ }
} ;

// class IAdaptor,抽象基類
class IAdaptor
{
public:
virtual void Proc() = 0 ;
} ;

// class Adaptor
template
class Adaptor : public IAdaptor, private T //實現繼承
{
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() ;
 

  上面是示例而非實例,你也許更愿意看看它實際的運用。去下載作者所寫的代碼,好好欣賞一下吧。
C++設計模式之Abstract Factory
2002-07-23· · ··COM集中營

  一、功能
  提供一個創建一系列相關或相互依賴對象的接口,而無需指定它們具體的類。

  二、結構圖

  類廠最基本的結構示意圖如下:

 

  在實際應用中,類廠模式可以擴充到很復雜的情況,如下圖所示:

 


三、優缺點

  優點:(1)封裝創建過程。客戶不用知道類廠是如何創建類實例的,類廠封閉了所有創建的細節。這樣可選擇不同的創建方法,增加了靈活性。 (2)將客戶與具體類隔離,提高了各自的可重用性。
  缺點:Factory類層次與具體類層次通常是平行的(即一一對應的)。增加一個具體類,一般也要相應地增加一個factory類,增加了系統復雜度。

  四、實現

  (1)Abstract Factory類中通常是一組Factory Method的集合。個人認為與Factory Method模式沒有本質區別。

  (2)通常可以把工廠作為單件。
  五、示例代碼

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 ;
  // 第一種創建方法

  AbstractFactory *pFactory = ConcreteFactory1::Instance() ;
  AbstractProductA *pProductA = pFactory->CreateProductA() ;
  AbstractProductB *pProductB = pFactory->CreateProductB() ;

  // 第二種創建方法
  pFactory = ConcreteFactory2::Instance() ;
  pProductA = pFactory->CreateProductA() ;
  pProductB = pFactory->CreateProductB() ;
}

  六、實例

  最早知道類廠的概念是在COM中,但當時也沒想到這是如此重要的一種模式,在許多其他模式中都可以用到類廠模式。 COM中不能直接創建組件,這也是由COM的一個特性決定的:即客戶不知道要創建的組件的類名。

C++設計模式之Singleton
2002-07-26· · ··COM集中營

  一、功能

  保證一個類僅有一個實例。

  二、結構圖



三、優缺點

  Singleton模式是做為"全局變量"的替代品出現的。所以它具有全局變量的特點:全局可見、貫穿應用程序的整個生命期,它也具有全局變量不具備的性質:同類型的對象實例只可能有一個。

  四、實現

  教科書上的Singleton定義如下:


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)因為返回的是指針,為防止用戶調用delete函數,可把static Singleton *_instance;改為在Instance()中定義static Singleton _instance。這樣顯然更安全,同時也具有lazy initialization的特性(即第一次訪問時才創建)。

  (2)假設需要從Singleton派生子類,而子類也需要有同樣的性質,既只能創建一個實例。我覺得,這很難辦。根本原因在于Instance()函數不是虛函數,不具有多態的性質。一種常用方法是把Instance()函數移到子類中,這時就只能用static Singleton *_instance,而不能用static Singleton _instance了,除非把_instance也要移到子類,無論怎么做都不優雅。另一種方法是用模板。具體用什么方法,只能根據實際情況權衡。

  五、示例代碼

  (1)沒子類的情況

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)有子類的情況


方法一:
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 > {} ;
}

客戶端代碼
{
using namespace DesignPattern_Singleton ;

ConcreteSingleton *p = ConcreteSingleton::Instance() ;
}
 
 
C++模式開發之Bridge
2002-07-29· · ··COM集中營

  一、功能
  將抽象部分與它的實現部分分離,使它們都可以獨立地變化。

  二、結構圖


三、示例代碼
namespace DesignPattern_Bridge
{
// class Implementor
class Implementor
{
public:
virtual void OperationImp() = 0 ;
} ;

// 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) ; //第一種實現方法
obj.Operation(impb) ; //第二種實現方法
}
 


  四、實例

  (1)創建可以在X Window System和IBM的Presentation Manager系統中都可以使用的窗口。(書上的例子)


Bridge的魅力在于抽象和實現之間是松散的關系,它們之間可以進行隨意組合。如上圖中,就有IconWindow+XWindowImp、TransientWindow+XWindowImp、IconWindow+PMWindowImp、TransientWindow+PMWindowImp四種組合。

C++模式設計之Builder
2002-07-30· · ··COM集中營

  一、功能

  將一個復雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示

  二、結構圖

各類之間的交互關系如下圖所示:


三、示例代碼

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 ; } //返回創建的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 ; } //返回創建的Product2對象
private:
Product2 *_product ;
} ;

// class Director
class Director
{
public:
//創建對象(Director并不知道具體創建出來的對象是什么樣的,只有調用該函數的client知道)
void Construct(Builder *builder)
{
builder->BuilderPartA() ;
builder->BuilderPartB() ;
builder->BuilderPartC() ;
}
} ;
}

客戶端代碼:
{
using namespace DesignPattern_Builder ;

Director director ;

// 創建第一種對象
ConcreteBuilder1 *pBuilder1 = new ConcreteBuilder1() ;
director.Construct(pBuilder1) ;
Product1 *product1 = pBuilder1->GetProduct1() ;

// 創建第二種對象
ConcreteBuilder2 *pBuilder2 = new ConcreteBuilder2() ;
director.Construct(pBuilder2) ;
Product2 *product2 = pBuilder2->GetProduct2() ;
}
 


  四、實例

  (1)例子一。如下圖所示:



上圖的功能是是把一個RTF文件轉換為多種正文格式。RTFReader進行語法分析,然后將所有的token串逐一轉換。可見builder就是一步步地把各個部分組裝為一個整體。它封閉了組裝的方法,組裝出來的對象也大相徑庭。

C++設計模式之Prototype
2002-08-01· · ··COM集中營

  一、功能

  用原型實例指定創建對象的種類,并且通過拷貝這些原型創建新的對象。



  二、結構圖


三、優缺點

  優點:復制自身。客戶不知道需要對象的實際類型,只需知道它的抽象基類即可。(即有繼承樹的情況)

  缺點:必須先有一個對象實例(即原型)才能clone。

  四、示例代碼

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
}
 

  五、實例

     在一個圖形編輯器中,每一個圖形元素,如線、圓、文字等都應該支持拷貝操作,即點中圖形,按下Ctrl+C,再按下Ctrl+V后就會復制一個新的圖形。顯然這是一種clone操作。所以在每個從Graphic派生出的圖形子類都應運用Prototype模式,加上Clone操作。
 

C++設計模式之Factory Method
2002-08-05· · ··COM集中營

  一、功能

  定義一個用于創建對象的接口,讓子類決定實例化哪一個類。Factory Method 使一個類的實例化延遲到其子類。

  二、結構圖


三、實現

(1)在某些情況下,比如僅僅為了創建適當的Product對象而派生新的Creator子類,并且創建不同Product的方法一致時,可以考慮用模板代替繼承。如:

class Creator
{
public:
virtual Product* CreateProduct() = 0 ;
};

template < class ConcreteProduct >
class ConcreteCreator: public Creator
{
public:
virtual Product* CreateProduct() { return new ConcreteProduct() ; }
};

    模板與繼承的本質區別之一是:模板:行為不依賴于類型。繼承:行為依賴于類型。(Effective C++ Item 41) 事實上,在很多模式中都存在著可以用模板代替繼承的情況,其根本原因就在于子類的行為是一致的。

  四、示例代碼

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() ;
}
 

    這里的CreateProduct其實也是一個Template Method。

  五、實例

  Factory Method的運用太廣泛了,它經常運用在其它模式中,其實例舉不勝數。
(1)


MFC中的CDocument類就包含了類似于上圖CApplication中的三個函數。這里的CreateDocument就是一個factory method,因為它負責創建一個文檔對象。

  (2)


當一個類將它的一些職責委托給一個獨立的類時,就產生了平行類層次。上圖中Figure和Manipulator就是平行類層次,Figure代表一些圖形元素,如線、文字等,Manipulator表示作用于這些圖形元素的操作,如拖拉、移動、選中等。如果這些操作所需要的狀態信息并不需要保存在Figure中,那么把Figure和Manipulator分成兩個類層次是個好主意。這里的CreateManipulator就是一個factory method。

C++設計模式之Composite
2002-08-06· · ··COM集中營

  一、功能
  表示“部分-整體”關系,并使用戶以一致的方式使用單個對象和組合對象。

  二、結構圖


上圖中,也可以做些擴展,根據需要可以將Leaf和Composite做為抽象基類,從中派生出子類來。

  三、優缺點

  優點:對于Composite模式,也許人們一開始的注意力會集中在它是如何實現組合對象的。但Composite最重要之處在于用戶并不關心是組合對象還是單個對象,用戶將以統一的方式進行處理,所以基類應是從單個對象和組合對象中提出的公共接口。
  缺點:Composite最大的問題在于不容易限制組合中的組件。

  四、實現

  有時需要限制組合中的組件,即希望一個Composite只能有某些特定的Leaf。這個問題我是用多繼承和動態類型轉換來解決的。假如組合對象Composite1只能包含單個對象ConcreteLeaf1,Composite2可以包含單個對象ConcreteLeaf1和ConcreteLeaf2。如下圖所示:


上圖中的類層次比較多,使用了AbstractLeaf1和AbstractLeaf2,但沒使用AbstractComposite1和AbstractComposite2,這個并不重要,也可以把AbstractLeaf1和AbstractLeaf2去掉,這個并不重要,可以根據具體情況決定要不要。
簡單的代碼實現如下:

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_cast<ABSTRACTCOMPONENT1*>(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_cast<ABSTRACTCOMPONENT2*>(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 */ }
} ;
}

客戶端代碼:

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
}
 


  有兩點需要注意,一是因為用了多繼承,所以需要使用virtual inheritance。二是要用dynamic_cast來判斷是否允許組合該組件。

  五、示例代碼

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 ;
} ;
}
 

  六、實例

  (1)JUnit中就用的是Composite模式。

 

posted on 2011-04-13 17:47 厚積薄發 閱讀(295) 評論(0)  編輯 收藏 引用 所屬分類: 設計模式


只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


導航

<2025年11月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

統計

常用鏈接

留言簿

隨筆分類

文章分類

文章檔案

搜索

最新評論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美色图五月天| 久久精品免视看| 亚洲夫妻自拍| 亚洲摸下面视频| 性做久久久久久免费观看欧美| 欧美三日本三级三级在线播放| 欧美日韩在线观看视频| 亚洲永久免费视频| 欧美激情精品久久久六区热门| 一本色道久久综合狠狠躁篇怎么玩| 欧美电影免费观看大全| 亚洲校园激情| 亚洲国产三级在线| 久久成人免费| 亚洲女人天堂成人av在线| 韩国v欧美v日本v亚洲v| 牛夜精品久久久久久久99黑人 | 欧美在线视频一区二区三区| 性8sex亚洲区入口| 裸体丰满少妇做受久久99精品 | 久久久精彩视频| 99精品欧美一区二区蜜桃免费| 国产偷自视频区视频一区二区| 欧美黑人多人双交| 久久精品综合一区| 99re这里只有精品6| 亚洲精选中文字幕| 一区视频在线看| 国产精品美女在线观看| 久久久爽爽爽美女图片| 亚洲欧美日韩中文视频| 亚洲九九精品| 亚洲国产精品日韩| 亚洲一线二线三线久久久| 久久久综合网| 国产精品视频久久| 国产精品中文在线| 欧美日韩中文字幕在线| 一区二区视频在线观看| 亚洲欧美日韩精品综合在线观看| 欧美xx视频| 六十路精品视频| 亚洲字幕在线观看| 欧美日韩国产成人在线91| 欧美国产视频在线观看| 国产欧美欧洲在线观看| 国产热re99久久6国产精品| 亚洲丰满少妇videoshd| 一本色道久久综合狠狠躁的推荐| 国产精品欧美一区二区三区奶水 | 久热re这里精品视频在线6| 久久国内精品自在自线400部| 亚洲欧美美女| 欧美三区在线视频| 一本在线高清不卡dvd| 亚洲大片免费看| 久久久蜜臀国产一区二区| 国产一区91精品张津瑜| 亚洲第一网站| 亚洲三级电影在线观看| 一区二区免费在线观看| 午夜伦理片一区| 久久久久欧美| 亚洲二区视频在线| 麻豆精品传媒视频| 欧美性大战久久久久久久蜜臀| 国产精品女同互慰在线看| 一区电影在线观看| 亚洲精品系列| 欧美午夜无遮挡| 欧美一进一出视频| 牛牛影视久久网| 久久久久一区| 最近中文字幕日韩精品| 午夜精品久久久久久久久久久久久 | 毛片一区二区三区| 日韩一二三区视频| 一区二区三区 在线观看视频| 欧美在线视频全部完| 欧美二区在线| 亚洲裸体视频| 亚洲男女毛片无遮挡| 韩日精品在线| 亚洲福利精品| 国产精品日韩欧美大师| 久久久久久久999| 欧美大片免费看| 午夜精品久久久久久久99黑人| 久久国产精品久久久久久久久久| 91久久亚洲| 午夜在线播放视频欧美| 欧美三级日本三级少妇99| 亚洲欧美制服另类日韩| 久久久久久久综合日本| 99视频精品在线| 欧美一区二区三区另类| 欧美日韩一区在线| 久久精品视频播放| 欧美国产日韩一区二区| 午夜视黄欧洲亚洲| 免费观看亚洲视频大全| 欧美激情1区2区| 欧美日韩一区在线| 久久午夜色播影院免费高清| 一区二区三区国产精品| 国产一区二区三区的电影 | 欧美日韩精品免费| 久久久久久久久久看片| 欧美日韩免费一区二区三区| 久久久久久久久蜜桃| 欧美日韩麻豆| 欧美多人爱爱视频网站| 久久精品99| 国产精品99久久久久久久女警| 另类亚洲自拍| 国产精品视频久久一区| 亚洲国产日韩欧美在线图片| 国产主播精品在线| 美女精品一区| 久久综合伊人77777尤物| 亚洲综合99| 亚洲一区二区少妇| 亚洲精品日本| 久久只精品国产| 久久亚洲欧美国产精品乐播| 国产精品久久久久秋霞鲁丝| 亚洲福利国产| 亚洲人成网站色ww在线| 久久天天综合| 99天天综合性| 欧美www在线| 麻豆精品视频在线观看| 国产亚洲激情| 性欧美暴力猛交69hd| 欧美一区二区三区精品| 国产精品成av人在线视午夜片| 日韩视频中文| 亚洲午夜日本在线观看| 亚洲欧美日韩国产中文| 亚洲一区美女视频在线观看免费| 欧美极品在线播放| 午夜精品国产| 国产美女扒开尿口久久久| 一区二区三区日韩欧美精品| 亚洲婷婷综合久久一本伊一区| 欧美国产欧美亚洲国产日韩mv天天看完整 | 亚洲欧美日本国产专区一区| 亚洲伊人久久综合| 国产精品专区h在线观看| 亚洲欧美日韩在线观看a三区| 欧美专区在线观看一区| 国产曰批免费观看久久久| 欧美中文在线字幕| 欧美韩日精品| 一区二区三区黄色| 国产精品一二三四| 久久久久久久97| 亚洲欧洲日韩女同| 国产视频精品网| 亚洲制服丝袜在线| 国产精品一区二区久久精品| 欧美电影在线观看完整版| 亚洲日本理论电影| 国产精品草莓在线免费观看| 欧美一区二区三区日韩| 免费观看日韩| 亚洲一区二区三区欧美| 国产女主播在线一区二区| 久久久精品视频成人| 亚洲国内精品在线| 午夜在线观看免费一区| 精品va天堂亚洲国产| 欧美日韩美女在线| 久久精品视频在线播放| 亚洲另类自拍| 美女视频网站黄色亚洲| 中文在线资源观看网站视频免费不卡| 国产精品日韩在线一区| 久久婷婷蜜乳一本欲蜜臀| 这里只有精品视频| 99精品久久久| 国产一区三区三区| 欧美激情第六页| 久久成人综合视频| 一区二区三区av| 亚洲黄色高清| 久久伊人精品天天| 小黄鸭精品密入口导航| 99国产精品| 一区精品在线| 国产精品一区二区三区四区五区| 免费一级欧美在线大片| 欧美亚洲一级| 中文久久精品| 日韩视频―中文字幕| 欧美高清不卡| 免费人成精品欧美精品| 欧美在线观看一区二区| 亚洲网友自拍| 一区二区三区国产在线观看|