c++设计模式之桥接模式

来源:互联网 发布:c语言反斜杠怎么打 编辑:程序博客网 时间:2024/05/16 10:57

                                                                                             c++设计模式之桥接模式     

作用:将抽象部份与它的实现部份分离,使它们都可以独立地变化。将抽象(Abstraction)与实现(Implementation)分离,使得二者可以独立地变化。

 

                     

桥接模式就将实现与抽象分离开来,使得RefinedAbstraction依赖于抽象的实现,这样实现了依赖倒转原则,而不管左边的抽象如何变化,只要实现方法不变,右边的具体实现就不需要修改,而右边的具体实现方法发生变化,只要接口不变,左边的抽象也不需要修改。


#include<iostream>
using namespace std;
/*
桥接模式
*/




/*
实现基类
*/ 
class AbstractionImp{
public:
virtual void operation() = 0; 
virtual ~AbstractionImp(){}
};
class ConcreteAbstractionImpA:public AbstractionImp{
public:
void operation(){
cout<<" ConcreteAstractionImpA"<<endl;
}
~ConcreteAbstractionImpA(){
cout<<"ConcreteAbstractionImpA's ~"<<endl;
}
};
class ConcreteAbstractionImpB:public AbstractionImp{
public:
void operation(){
cout<<" ConcreteAstractionImpB"<<endl;
}
~ConcreteAbstractionImpB(){
cout<<"ConcreteAbstractionImpB's ~"<<endl;
}
};
/*
抽象基类
*/ 
class Abstraction{
private:
  AbstractionImp *aImp; 
public:
Abstraction(AbstractionImp *aImp){
this -> aImp = aImp; 
}
virtual void operation() = 0;
virtual ~Abstraction(){
}
void inter()
{
aImp ->operation();

};
class RefindAbstraction1:public Abstraction{
public:
RefindAbstraction1(AbstractionImp * aImp):Abstraction(aImp){
}
void operation(){
     cout<<"RefindAbstraction1 is on";
 inter();
}
~RefindAbstraction1(){
cout<<"RefindAbstraction1's ~"<<endl;
}
};
class RefindAbstraction2:public Abstraction{
public:
RefindAbstraction2(AbstractionImp * aImp):Abstraction(aImp){
}
void operation(){
cout<<"RefindAbstraction2 is on";
inter();
}
~RefindAbstraction2(){
cout<<"RefindAbstraction2's ~"<<endl;
}
};
int main (void)
{
ConcreteAbstractionImpA *cAIa= new ConcreteAbstractionImpA();
Abstraction *Ra1 = new RefindAbstraction1(cAIa);
Ra1 -> operation(); 
delete cAIa;
delete Ra1; 
return 0;
}

例子:

手机品牌和软件是两个概念,不同的软件可以在不同的手机上,不同的手机可以有相同的软件,两者都具有很大的变动性。如果我们单独以手机品牌或手机软件为基类来进行继承扩展的话,无疑会使类的数目剧增并且耦合性很高

常用的场景
1.当一个对象有多个变化因素的时候,考虑依赖于抽象的实现,而不是具体的实现。如上面例子中手机品牌有2种变化因素,一个是品牌,一个是功能。

2.当多个变化因素在多个对象间共享时,考虑将这部分变化的部分抽象出来再聚合/合成进来,如上面例子中的通讯录和游戏,其实是可以共享的。

3.当我们考虑一个对象的多个变化因素可以动态变化的时候,考虑使用桥接模式,如上面例子中的手机品牌是变化的,手机的功能也是变化的,所以将他们分离出来,独立的变化。

优点
1.将实现抽离出来,再实现抽象,使得对象的具体实现依赖于抽象,满足了依赖倒转原则。

2.将可以共享的变化部分,抽离出来,减少了代码的重复信息。

3.对象的具体实现可以更加灵活,可以满足多个因素变化的要求。

缺点
1.客户必须知道选择哪一种类型的实现。


考虑装操作

系统,

有多种配置的计算机,

同样也有多款操作系统。

如何运用桥接模式呢?可以将操作系统和

计算机分别抽象出来,让它们各自发展,减少它们的耦合度。当然了,两者之间有标准的接口。

这样设计,不论是对于计算机,还是操作系统都是非常有利的。

考虑装操作系统,有多种配置的计算机,同样也有多款操作系统。如何运用桥接模式呢?可以将操作系统和计算机分别抽象出来,让它们各自发展,减少它们的耦合度。当然了,两者之间有标准的接口。这样设计,不论是对于计算机,还是操作系统都是非常有利的。

                  

#include<iostream>
using namespace std;
/*
实现基类 
*/
class Os{
public:
virtual void install_imp() = 0;
virtual ~Os (){};
};




/*
具体实现类 
*/ 
class LinuxOS:public Os{
public:
void install_imp(){
cout<<"安装linux系统!!"<<endl;
}
};
class windowsOS:public Os{
public:
void install_imp(){
cout<<"安装windows系统!!"<<endl;
}
};
class unixOS:public Os{
public:
void install_imp(){
cout<<"安装unix系统!!"<<endl;
}
};




/*
抽象基类 
*/ 
class computer{
private:
Os * os;
string name;
public:
computer(Os *os,string name){
this->os = os;
this->name = name;
}
virtual void install() = 0;
void inter(){
   cout<<name<<":";
os->install_imp();
}
};




/*
具体抽象类 
*/ 
class Applecomputer:public computer{
public:
Applecomputer(Os *os):computer(os,"Applecomputer"){} 
void install(){
inter();
}
};
class dellcomputer:public computer{
public:
dellcomputer(Os *os):computer(os,"dellcomputer"){} 
void install(){
inter();
}
};
class lenovocomputer:public computer{
public:
lenovocomputer(Os *os):computer(os,"lenovocomputer"){} 
void install(){
inter();
}
};
int main (void)
{
Os * po1 = new windowsOS();
Os * po2 = new LinuxOS();
computer * pc1 = new lenovocomputer(po1);
computer * pc2 = new dellcomputer(po2);
pc1->install();
pc2->install();
delete po1;
delete po2;
delete pc1;
delete pc2;
return 0;



备注:

由于实现的方式有多种,桥接模式的核心就是把这些实现独立出来,让他们各自变化。

将抽象部分与它的实现部分分离:实现系统可能有多角度(维度)分类,每一种分类都可能变化,那么就把这种多角度分离出来让它们独立变化,减少它们之间的耦合。

在发现需要多角度去分类实现对象,而只用继承会造成大量的类增加,不能满足开放-封闭原则时,就要考虑用Bridge桥接模式了。

合成/聚合复用原则:尽量使用合成/聚合,精良不要使用类继承。
优先使用对象的合成/聚合将有助于保持每个类被封装,并被集中在单个任务上。这样类和类继承层次会保持较小规模,并且不太可能增长为不可控制的庞然大物。



0 0