常用的几种设计模式

一 Bridge模式
将抽象部分与它的实现部分分离,使它们都可以独立地变化。
Bridge模式将继承关系转换为组合关系,从而降低了系统间的耦合,减少了代码编写量.
抽象化

存在于多个实体中的共同的概念性联系,就是抽象化。作为一个过程,抽象化就是忽略一些信息,从而把不同的实体当做同样的实体对待【LISKOV94】。

实现化

抽象化给出的具体实现,就是实现化。

脱耦

所谓耦合,就是两个实体的行为的某种强关联。而将它们的强关联去掉,就是耦合的解脱,或称脱耦。在这里,脱耦是指将抽象化和实现化之间的耦合解脱开,或者说是将它们之间的强关联改换成弱关联。

将两个角色之间的继承关系改为聚合关系,就是将它们之间的强关联改换成为弱关联。因此,桥梁模式中的所谓脱耦,就是指在一个软件系统的抽象化和实现化之间使用组合/聚合关系而不是继承关系,从而使两者可以相对独立地变化。这就是桥梁模式的用意。

抽象化(Abstraction)角色:抽象化给出的定义,并保存一个对实现化对象的引用。
修正抽象化(Refined Abstraction)角色:扩展抽象化角色,改变和修正父类对抽象化的定义。
实现化(Implementor)角色:这个角色给出实现化角色的接口,但不给出具体的实现。必须指出的是,这个接口不一定和抽象化角色的接口定义相同,实际上,这两个接口可以非常不一样。实现化角色应当只给出底层操作,而抽象化角色应当只给出基于底层操作的更高一层的操作。
具体实现化(Concrete Implementor)角色:这个角色给出实现化角色接口的具体实现。

interface AbstractImp
{
 virtual void Operator() = 0;
};

interface AbstractInterface
{
 virtual void Operator() = 0;
 virtual void SetAbstractImp(AbstractImp* pAbstractImp) = 0;
};

class RefindedAbstract : public AbstractInterface
{
public:
 void Operator()
 {
  m_pABstractImp->Operator();
 }
 void SetAbstractImp(AbstractImp* pAbstractImp)
 {
  m_pABstractImp = pAbstractImp;
 }
private:
 AbstractImp* m_pABstractImp;

};

class CImpA : public AbstractImp
{
public:
 void Operator()
 {
  cout << "A imp !" << endl;
 }
};

class CImpB : public AbstractImp
{
public:
 void Operator()
 {
  cout << " B Imp !" << endl;
 }
};

二 组合模式
将对象组合成树形结构以表示“部分-整体”的层次结构。
抽象构件(Component)角色:这是一个抽象角色,它给参与组合的对象规定一个接口。这个角色给出共有接口及其默认行为。
树叶构件(Leaf)角色:代表参加组合的树叶对象。一个树叶对象没有下级子对象。
树枝构件(Composite)角色:代表参加组合的有子对象的对象,并给出树枝构件对象的行为。
可以看出,Composite类型的对象可以包含其它Component类型的对象。换而言之,Composite类型对象可以含有其它的树枝(Composite)类型或树叶(Leaf)类型的对象。

合成模式的实现根据所实现接口的区别分为两种形式,分别称为安全模式和透明模式。合成模式可以不提供父对象的管理方法,但合成模式必须在合适的地方提供子对象的管理方法(诸如:add、remove、getChild等)。

透明方式
作为第一种选择,在Component里面声明所有的用来管理子类对象的方法,包括add()、remove(),以及getChild()方法。这样做的好处是所有的构件类都有相同的接口。在客户端看来,树叶类对象与合成类对象的区别起码在接口层次上消失了,客户端可以同等同的对待所有的对象。这就是透明形式的合成模式。

这个选择的缺点是不够安全,因为树叶类对象和合成类对象在本质上是有区别的。树叶类对象不可能有下一个层次的对象,因此add()、remove()以及getChild()方法没有意义,是在编译时期不会出错,而只会在运行时期才会出错。
安全方式

第二种选择是在Composite类里面声明所有的用来管理子类对象的方法。这样的做法是安全的做法,因为树叶类型的对象根本就没有管理子类对象的方法,因此,如果客户端对树叶类对象使用这些方法时,程序会在编译时期出错。

这个选择的缺点是不够透明,因为树叶类和合成类将具有不同的接口。

class DrawEelem
{
public:
 DrawEelem()
 {
 }
 DrawEelem(const char* name)
 {
  m_name = name;
 }
 virtual void Draw() = 0;
protected:
 const char* m_name;
};

class Leaf : public DrawEelem
{
public:
 Leaf(const char * name): DrawEelem(name)
 {

 }
 virtual void Draw()
 {
  cout << m_name << endl;
 }

};

class CompositeEleem : public DrawEelem
{
public:
 CompositeEleem()
 {

 }
 void Add(DrawEelem * pDrawElem)
 {
  m_list.push_back(pDrawElem);
 }
 void Remove(DrawEelem* pDrawElem)
 {
 }
 void Draw()
 {
  list ::iterator pos;
  for (pos = m_list.begin(); pos != m_list.end(); ++pos)
   (*pos)->Draw();
 }
private:
 list m_list;
};


三 装饰模式
动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式相比生成子类更加灵活.
饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。
抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象。
具体构件(Concrete Component)角色:定义一个将要接收附加责任的类。
装饰(Decorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。
具体装饰(Concrete Decorator)角色:负责给构件对象"贴上"附加的责任。
class Component
{
public:
 virtual void Draw() = 0;
};

class TextView : public Component
{
public:
 void Draw()
 {
  cout << "画正文!" << endl;
 }
};

class Decorator : public Component
{
public:
 Decorator(Component* pComonent)
 {
  m_pComponent = pComonent;
 }
 void Draw()
 {
  m_pComponent->Draw();
 }
private:
 Component* m_pComponent;
};

class BroderDecorator : public Decorator
{
public:
 BroderDecorator(Component* pComponent) : Decorator(pComponent)
 {

 }
 void Draw()
 {
  Decorator::Draw();
  DrawBorder();
 }
private:
 void DrawBorder()
 {
  cout << "画边框!" <
 }
};

class ScrollDecorator : public Decorator
{
public:
 ScrollDecorator(Component* pComponent) : Decorator(pComponent)
 {

 }
 void Draw()
 {
  Decorator::Draw();
  DrawScroll();
 }
private:
 void DrawScroll()
 {
  cout << "画滚动条!" << endl;
 }
};
//这是一个使用者
class Window
{
public:
 Window()
 {
  m_pComponent = NULL;
 }
 void SetComponent(Component* pComponent)
 {
  m_pComponent = pComponent;
 }
 void Draw()
 {
  m_pComponent->Draw();
 }
private:
 Component* m_pComponent;
};


四 观察者模式
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
一个软件系统常常要求在某一个对象的状态发生变化的时候,某些其它的对象做出相应的改变。做到这一点的设计方案有很多,但是为了使系统能够易于复用,应该选择低耦合度的设计方案。减少对象之间的耦合有利于系统的复用,但是同时设计师需要使这些低耦合度的对象之间能够维持行动的协调一致,保证高度的协作(Collaboration)。观察者模式是满足这一要求的各种设计方案中最重要的一种。

抽象主题(Subject)角色:主题角色把所有对观察考对象的引用保存在一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象,主题角色又叫做抽象被观察者(Observable)角色,一般用一个抽象类或者一个接口实现。
抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。这个接口叫做更新接口。抽象观察者角色一般用一个抽象类或者一个接口实现。在这个示意性的实现中,更新接口只包含一个方法(即Update()方法),这个方法叫做更新方法。
具体主题(ConcreteSubject)角色:将有关状态存入具体现察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色又叫做具体被观察者角色(Concrete Observable)。具体主题角色通常用一个具体子类实现。
具体观察者(ConcreteObserver)角色:存储与主题的状态自恰的状态。具体现察者角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。如果需要,具体现察者角色可以保存一个指向具体主题对象的引用。具体观察者角色通常用一个具体子类实现。

class Observer
{
public:
 virtual ~Observer()
 {

 }
 virtual void Update(SubjectBase* pSubject) = 0;
protected:
 Observer()
 {

 }
};

//目标者
class SubjectBase
{
public:
 virtual ~SubjectBase()
 {

 }
public:
 virtual void Attach(Observer* pObserver)
 {
  m_Observers.push_back(pObserver);
 }
 virtual void Detach(Observer* pObserver)
 {
  list ::iterator it;
  it = find(m_Observers.begin(), m_Observers.end(), pObserver);
  if (it != m_Observers.end())
  m_Observers.erase(it);
 }
 virtual void Notify()
 {
  list ::iterator it = m_Observers.end();
  for (; it != m_Observers.end(); ++it)
   (*it)->Update(this);
 }
protected:
 SubjectBase()
 {
 }
private:
 list m_Observers;
};

class Timer : public SubjectBase
{
public:
 Timer()
 {
  m_hour = 0;
 }
 int GetHour()
 {
  return m_hour;
 }
 void SetHour(int hour)
 {
  m_hour = hour;
 }
private:
 int m_hour;
};
class DigitalClock : public Observer
{
public:
 DigitalClock(Timer* pTimer)
 {
  m_pTimer = pTimer;
  m_pTimer->Attach(this);
 }
 virtual ~DigitalClock()
 {
  m_pTimer->Detach(this);
 }
 virtual void Update(SubjectBase* pSubject)
 {
  if (pSubject == m_pTimer)
   Show();
 }
 virtual void Show()
 {
  int hour = m_pTimer->GetHour();
  cout << "数字:" << hour << endl;
 }
private:
 Timer* m_pTimer;
};

class AnalogClock : public Observer
{
public:
 void Update(SubjectBase* pSubject)
 {

 }
};


五 Builder模式
建造者模式可以将一个产品的内部表象与产品的生成过程分割开来,从而可以使一个建造过程生成具有不同的内部表象的产品对象。

建造者(Builder)角色:给出一个抽象接口,以规范产品对象的各个组成成分的建造。一般而言,此接口独立于应用程序的商业逻辑。模式中直接创建产品对象的是具体建造者(ConcreteBuilder)角色。具体建造者类必须实现这个接口所要求的方法:一个是建造方法,另一个是结果返还方法。

具体建造者(Concrete Builder)角色:担任这个角色的是于应用程序紧密相关的类,它们在应用程序调用下创建产品实例。这个角色主要完成的任务包括:

实现Builder角色提供的接口,一步一步完成创建产品实例的过程。
在建造过程完成后,提供产品的实例。
指导者(Director)角色:担任这个角色的类调用具体建造者角色以创建产品对象。导演者并没有产品类的具体知识,真正拥有产品类的具体知识的是具体建造者对象。

产品(Product)角色:产品便是建造中的复杂对象。

class Product    //假设Product是由一系列的东西组成的
{
public:
 Product()
 {

 }
 ~Product()
 {
 }
public:
 void Add(string str)
 {
  m_ProductList.push_back(str);
 }
 void Show()
 {
  list ::iterator it;
  for (it = m_ProductList.begin(); it != m_ProductList.end(); ++it)
   cout << (*it) << endl;
 }
private:
 list m_ProductList;
};

class Builder
{
public:
 virtual void BuildPartA() {}
 virtual void BuildPartB(){}
 virtual Product* GetResult(){return NULL;}
};

class ConcreteBuilder : public Builder
{
public:
 ConcreteBuilder()
 {
  m_Product = NULL;
 }
public:
 void BuildPartA()
 {
  m_Product = new Product();
  m_Product->Add("AAAA");
 }
 void BuildPartB()
 {
  m_Product->Add("bbb");
 }
 Product*  GetResult()
 {
  return m_Product;
 }
private:
 Product* m_Product;
};

class Director
{
public:
 void Construct(Builder& builder)
 {
  builder.BuildPartA();
  builder.BuildPartB();
 }
};

六 单件模式
单例类只能有一个实例。
单例类必须自己创建自己的唯一实例。
单例类必须给所有其它对象提供这一实例。
class Singleton
{
 public:
  static Singleton* CreateInstance();
  {
   static Singleton _instance;
    return &_instance;
  }
};

template
class Singleton
{
  public:
   static T* CreateInstance()
   {
    static T _instance;
    return &_instance;
   }
  private:
   Singleton(const Singleton);
   Singleton &operator = (const Singleton);
};

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值