设计的7大原则:
开闭原则:软件实现应当对扩展开放,对修改关闭。
里氏替换原则:继承必须确保超类所拥有的性质在子类中仍然成立。
依赖倒置原则:高层模块不应该依赖低层模块,两则都应该依赖其抽象;抽象不应该依赖细节, 细节应该依赖抽象。
单一职责原则:一个类应该有且仅有一个引起他变化的原因,否则类应该被拆分
接口隔离原则:一个类对另一个类的应该建立在最小的接口上
迪米特法则:最少知识原则
合成复用原则:优先使用组合或者聚合,其次才考虑继承关系
从目的来看设计模式可分为三种:
工厂方法模式
动机
在软件系统中,经常面临着创建对象的工作;由于需求的变化,需要创建的对象的具体类型经常变化。如何应对这种变化?如何绕过常规的对象创建方法(new),提供一种“封装机制”来避免客户程序和这种“具体对象创建工作”的紧耦合。
模式定义
定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使得一个类的实例化延迟(目的:解耦,手段:虚函数)到子类。
简单工厂
工厂不遵循开闭原则
class AbstractFruit {
public:
virtual void showName() = 0;
};
class Apple : public AbstractFruit {
public:
virtual void showName() {
cout << "苹果" << endl;
}
};
class Banana : public AbstractFruit {
public:
virtual void showName() {
cout << "香蕉" << endl;
}
};
class Pear : public AbstractFruit {
public:
virtual void showName() {
cout << "鸭梨" << endl;
}
};
class FruitFactory {
public:
static AbstractFruit* CreateFruit(string flag) {
if (flag == "apple") {
return new Apple;
}
else if (flag == "banana")
return new Banana;
else if (flag == "pear")
return new Pear;
else
return nullptr;
}
};
void test01() {
FruitFactory* factory = new FruitFactory;
AbstractFruit* fruit = factory->CreateFruit("apple");
fruit->showName();
fruit = factory->CreateFruit("banana");
fruit->showName();
fruit = factory->CreateFruit("pear");
fruit->showName();
delete fruit;
}
int main() {
test01();
}
工厂方法模式
将工厂也抽象出来,让工厂也符合开闭原则。
//抽象水果
class AbstractFruit {
public:
virtual void showName() = 0;
};
//苹果
class Apple : public AbstractFruit {
public:
virtual void showName() {
cout << "苹果" << endl;
}
};
//香蕉
class Banana : public AbstractFruit {
public:
virtual void showName() {
cout << "香蕉" << endl;
}
};
//鸭梨
class Pear : public AbstractFruit {
public:
virtual void showName() {
cout << "鸭梨" << endl;
}
};
//抽象工厂
class AbstractFactory {
public:
virtual AbstractFruit* CreateFruit() = 0;
};
//苹果工厂
class AppleFactory : public AbstractFactory {
public:
virtual AbstractFruit* CreateFruit() {
return new Apple;
}
};
//香蕉工厂
class BananaFactory : public AbstractFactory {
public:
virtual AbstractFruit* CreateFruit() {
return new Banana;
}
};
//鸭梨工厂
class PearFactory : public AbstractFactory {
public:
virtual AbstractFruit* CreateFruit() {
return new Pear;
}
};
void test01() {
AbstractFactory* factory = NULL;
AbstractFruit* fruit = NULL;
//创建一个苹果工厂
factory = new AppleFactory;
fruit = factory->CreateFruit();
fruit->showName();
//创建一个香蕉工厂
factory = new BananaFactory;
fruit = factory->CreateFruit();
fruit->showName();
delete fruit;
delete factory;
}
int main() {
test01();
}
总结
- Factory Method模式用于隔离类对象的使用者和具体类型之间的 耦合关系。面对一个经常变化的具体类型,紧耦合关系(new)会导 致软件的脆弱。
- Factory Method模式通过面向对象的手法,将所要创建的具体 象工作延迟到子类,从而实现一种扩展(而非更改)的策略,较好地解决了这种紧耦合关系。
抽象工厂模式
动机
在软件系统中,经常面临着“一系列相互依赖的对象”的创建工作;同时,由于需求的变化,往往存在更多系列对象的创建工作。
模式定义
提供一个接口,让该接口负责创建一系列“相关或者相互依赖的对象”,无需指定它们具体的类
class AbstractApple{
public:
virtual void showName() = 0;
};
class ChinaApple : public AbstractApple {
public:
virtual void showName(){
cout << "中国苹果" << endl;
}
};
class USApple : public AbstractApple {
public:
virtual void showName() {
cout << "美国苹果" << endl;
}
};
class AbstractBanana {
public:
virtual void showName() = 0;
};
class ChinaBanana : public AbstractBanana {
public:
virtual void showName() {
cout << "中国香蕉" << endl;
}
};
class USBanana : public AbstractBanana {
public:
virtual void showName() {
cout << "美国香蕉" << endl;
}
};
class AbstractPear {
public:
virtual void showName() = 0;
};
class ChinaPear : public AbstractPear{
public:
virtual void showName() {
cout << "中国鸭梨" << endl;
}
};
class USPear : public AbstractPear {
public:
virtual void showName() {
cout << "美国鸭梨" << endl;
}
};
class AbstractFactory {
public:
virtual AbstractApple* CreateApple() = 0;
virtual AbstractBanana* CreateBanana() = 0;
virtual AbstractPear* CreatePear() = 0;
};
class ChinaFactory : public AbstractFactory {
public:
virtual AbstractApple* CreateApple() {
return new ChinaApple;
}
virtual AbstractBanana* CreateBanana() {
return new ChinaBanana;
}
virtual AbstractPear* CreatePear() {
return new ChinaPear;
}
};
class USFactory : public AbstractFactory {
public:
virtual AbstractApple* CreateApple() {
return new USApple;
}
virtual AbstractBanana* CreateBanana() {
return new USBanana;
}
virtual AbstractPear* CreatePear() {
return new USPear;
}
};
void test01() {
AbstractFactory* factory = NULL;
AbstractApple* apple = NULL;
AbstractBanana* banana = NULL;
AbstractPear* pear = NULL;
factory = new ChinaFactory;
apple = factory->CreateApple();
apple->showName();
banana = factory->CreateBanana();
banana->showName();
pear = factory->CreatePear();
pear->showName();
delete factory;
delete apple;
delete banana;
delete pear;
}
int main() {
test01();
}
总计
- 如果没有应对“多系列对象构建”的需求变化,则没有必要使用Abstract Factory模式,这时候使用简单的工厂完全可以
- “系列对象”指的是在某一特定系列下的对象之间有相互依赖、或作用的关系。不同系列的对象之间不能相互依赖。
- Abstract Factory模式主要在于应对“新系列”的需求变动。其缺点在于难以应对“新对象”的需求变动
单例模式
动机
在软件系统中,经常有这样一些特殊的类,必须保证他们在系统中只存在一个实例,才能确保他们的逻辑正确性、以及良好的效率。
模式定义
保证一个类只有一个实例,并且提供一个该实例的全局访问点。
线程不安全的懒汉模式
class singleClass {
public:
static singleClass* getInstance() { //对外的接口
//当多个线程同时访问时会有问题:比如两个线程同时访问到instance为NULL
if (instance == nullptr) {
instance = new singleClass();
}
return instance;
}
private:
//设置为static的原因:instance保存单例对象
//static修饰类内成员变量时表明其属于singleClass类而不是各个对象
//也就是说所有singleClass的对象共享这一份instance
static singleClass* instance; //单例为静态成员变量,类内声明,类外初始化
//如果构造函数是public,则外部可以初始化很多个singleClass,则就不是单例了。
singleClass() {}; //构造函数私有化
};
singleClass* singleClass::instance = nullptr; //类外初始化静态变量
int main() {
singleClass* single1 = singleClass::getInstance(); //获取唯一的单例
singleClass* single2 = singleClass::getInstance();
return 0;
}
线程安全的懒汉模式
class singleClass {
public:
static singleClass* getInstance() {
if (instance == nullptr) {
//实例还未创建则加锁
i_mutex.lock();
//再判断一次,确保不会因为加锁期间多个线程同时进入
if (instance == nullptr) {
instance = new singleClass;
}
i_mutex.unlock();
}
return instance;
}
private:
static singleClass* instance; //单例为静态成员变量,类内声明,类外初始化
static mutex i_mutex;
singleClass() {}; //构造函数私有化
};
singleClass* singleClass::instance = nullptr; //类外初始化静态变量
mutex singleClass::i_mutex;
饿汉模式
class singleClass {
public:
static singleClass* getInstance() {
return instance;
}
private:
static singleClass* instance;
singleClass() {};
};
//与懒汉模式不同的是:懒汉是第一次用到该类的时候才会实例化instance,而饿汉模式则在类一加载就实例化
//instance是静态的,在编译的时候就可以被初始化。也就是main函数之前已经被初始化
singleClass* singleClass::instance = new singleClass;
int main() {
singleClass* single1 = singleClass::getInstance();
singleClass* single2 = singleClass::getInstance();
return 0;
}
代理模式
动机
在面向对象系统中,有些对象由于某种原因(比如对象创建的开销很大,或者某些操作需要安全控制,或者需要进程外的访问等),直接访问会给使用者或系统结构带来麻烦。
模式定义
为其他对象提供一种代理以控制对这个对象的访问
class Subject {
public:
virtual void run() = 0;
};
class RealSubject: public Subject {
public:
virtual void run() {
cout << "Subject启动" << endl;
}
};
class Proxy: public Subject{
public:
Proxy(string username, string password) {
this->mUsername = username;
this->mPassword = password;
mySubject = new RealSubject;
}
bool check() {
if (mUsername == "123" && mPassword == "123")
return true;
return false;
}
virtual void run() {
if (check()) {
cout << "用户名和密码正确,验证通过" << endl;
mySubject->run();
}
else {
cout << "用户名和密码错误" << endl;
}
}
private:
string mUsername;
string mPassword;
RealSubject* mySubject;
};
int main() {
Proxy* proxy = new Proxy("123", "1234");
proxy->run();
}
总结
- 增加一层间接层是软件系统中对许多复杂问题的一种常见解决方法。在面向对象系统中,直接使用某些对象会带来很多问题,作为间接层的proxy对象便是解决这一问题的常用手段。
外观模式
动机
上述左边的方案问题在于组件的客户和组件中各种复杂的子系统有了过多的耦合,随着系外部客户程序和各子系统的演化,这种过多的耦合面临很多变化的挑战。
模式定义
为子系统中一组接口提供一个一致的界面,Faced模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
class SubSystem1 {
public:
void run() {
cout << "子系统1运行..." << endl;
}
};
class SubSystem2 {
public:
void run() {
cout << "子系统2运行..." << endl;
}
};
class SubSystem3 {
public:
void run() {
cout << "子系统3运行..." << endl;
}
};
class SubSystem4 {
public:
void run() {
cout << "子系统4运行..." << endl;
}
};
//外观类
class Facede {
public:
Facede() {
pSystem1 = new SubSystem1;
pSystem2 = new SubSystem2;
pSystem3 = new SubSystem3;
pSystem4 = new SubSystem4;
}
void runSystem() {
pSystem1->run();
pSystem2->run();
pSystem3->run();
pSystem4->run();
}
private:
SubSystem1* pSystem1;
SubSystem2* pSystem2;
SubSystem3* pSystem3;
SubSystem4* pSystem4;
};
int main() {
Facede* facede = new Facede;
facede->runSystem();
}
适配器模式
动机
在软件系统中,由于应用环境的变化,常常需要将一些现存的对象放在新的环境中应用,但是新环境需要的接口是这些现存对象所不满足的。
模式定义
讲一个类的接口转化成客户希望的另一个接口。Adapter式使得原本由于接口不兼容而不能在一起工作的哪些类可以一起工作
//现在有两个插口的充电器,但是只有三个插口的充电板
// 故需要将两个插口的充电器转换成三个插口的充电器
//三插口
class ThreeCharge {
public:
virtual void threeCharge() = 0;
};
//两插口
class TwoCharge {
public:
virtual void twoCharge() = 0;
};
class TwoChargeProcess : public TwoCharge {
virtual void twoCharge() {
cout << "使用两个插口充电" << endl;
}
};
//继承新接口,组合老接口
class Adapter : public ThreeCharge {
protected:
TwoCharge* twoCharge;
public:
Adapter(TwoCharge* twoCharge) {
this->twoCharge = twoCharge;
}
//转换处理
void twoTothree() {
//转换逻辑...
cout << "将两插口转换为三插口" << endl;
}
virtual void threeCharge() {
twoTothree();
cout << "使用三插口开始充电" << endl;
}
};
int main() {
TwoCharge* twoCharge = new TwoChargeProcess;
Adapter* adapter = new Adapter(twoCharge);
adapter->threeCharge();
}
模板方法模式
动机
在软件构建过程中,对于某一项任务,它常常有稳定的整体操作结构,但各个子步骤却有很多改变的需求,或者由于固有的原因(比如框架与应用之间的关系)而无法和任务的整体结构同时实现。
模式定义
定义一个操作中的算法的骨架(稳定的),而将一些步骤延迟(变化的)到子类中。Template Method使得子类可以不改变一个算法的结构即可重定义(override 重写)该算法的某些特定步骤。
模板方法模式结构图
class DrinkTemplate {
public:
virtual void BoilWater() = 0; //煮水
virtual void Brew() = 0; //冲泡
virtual void PourInCup() = 0; //倒入杯中
virtual void AddSomething() = 0; //加料
void make() {
BoilWater();
Brew();
PourInCup();
AddSomething();
}
};
//制作茶水
class Tea : public DrinkTemplate {
public:
virtual void BoilWater(){
cout << "煮开水" << endl;
}
virtual void Brew() {
cout << "冲泡茶叶" << endl;
}
virtual void PourInCup() {
cout << "茶水倒入杯中" << endl;
}
virtual void AddSomething() {
cout << "加入柠檬" << endl;
}
};
//制作咖啡
class Coffee : public DrinkTemplate {
public:
virtual void BoilWater() {
cout << "煮开水" << endl;
}
virtual void Brew() {
cout << "冲泡咖啡" << endl;
}
virtual void PourInCup() {
cout << "咖啡倒入杯中" << endl;
}
virtual void AddSomething() {
cout << "加入糖" << endl;
}
};
int main() {
Tea* tea = new Tea;
tea->make();
Coffee* coffee = new Coffee;
coffee->make();
}
策略模式
动机
在软件构建过程中,某些对象使用的算法可能多种多样,经常改变,如果将这些算法都编码到对象中,将会使对象变得异常复杂;而且有时候支持不使用的算法也是一个性能负担。
模式定义
定义一系列算法,把它们一个个封装起来,并且使它们可互相替换(变化)。该模式使得算法可独立于使用它的客户程序(稳定)而变化(扩展,子类化)。
策略模式实现
//武器策略
class WeaponStrategy {
public:
virtual void UseWeapon() = 0;
};
//匕首策略
class KnifeStrategy : public WeaponStrategy {
public:
virtual void UseWeapon() {
cout << "使用匕首" << endl;
}
};
//AK47策略
class AK47Strategy : public WeaponStrategy {
public:
virtual void UseWeapon() {
cout << "使用AK47" << endl;
}
};
class Character {
public:
//设置武器策略
void setWeaponStrategy(WeaponStrategy* weaponStrategy) {
this->pWeaponStrategy = weaponStrategy;
}
void useWeapon() {
pWeaponStrategy->UseWeapon();
}
private:
WeaponStrategy* pWeaponStrategy;
};
int main() {
Character* character = new Character; //创建角色
// 武器策略
WeaponStrategy* knife = new KnifeStrategy;
WeaponStrategy* ak47 = new AK47Strategy;
character->setWeaponStrategy(knife);
character->useWeapon();
character->setWeaponStrategy(ak47);
character->useWeapon();
delete character;
delete knife;
delete ak47;
}
总结
- Strategy及其子类为组件提供了一系列可重用的算法,从而可以使得类型在运行时方便地根据需要在各个算法之间进行切换
- Strategy模式提供了用条件判断语句以外的另一种选择,消除条件判断语句,就是在解耦合。含有许多条件判断语句的代码通常都需要Strategy模式
- 如果Strategy对象没有实例变量,那么各个上下文可以共享同一个Strategy对象,从而节省对象开销
命令模式
动机
在软件构建过程中,“行为请求者” 与 “行为实现者”通常呈现一种紧耦合。但在某些场合中,比如需要对行为进行记录、撤销、重做等处理,这种无法抵御变化的紧耦合是不合适的。
模式定义
将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
class AbstractCommand {
public:
virtual void handle() = 0;
};
//处理增加金币请求
class AddMoneyCommand : public AbstractCommand {
public:
virtual void handle() {
cout << "给玩家增加金币" << endl;
}
};
//处理升级请求
class AddLevelCommand : public AbstractCommand {
public:
virtual void handle() {
cout << "给玩家升级" << endl;
}
};
//服务器
class Server {
public:
void addRequest(AbstractCommand* command) {
mCommand.push(command);
}
void startHandle() {
while (!mCommand.empty()) {
AbstractCommand* command = mCommand.front();
command->handle();
mCommand.pop();
}
}
private:
queue<AbstractCommand*>mCommand;
};
int main() {
AbstractCommand* addMoney = new AddMoneyCommand();
AbstractCommand* addLevel = new AddLevelCommand();
Server* server = new Server;
server->addRequest(addMoney);
server->addRequest(addLevel);
server->startHandle();
}
观察者模式
动机
在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系” ——一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知。如果这样的依赖关系过于紧密,将使软件不能很好地抵御变化。
模式定义
定义对象间的一种一对多(变化)的依赖关系,以便当一个对象(Subject)的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。
class AbstractHero {
public:
virtual void Update() = 0;
};
class HeroA : public AbstractHero {
public:
HeroA() {
cout << "英雄A在打Boss" << endl;
}
virtual void Update() {
cout << "英雄A待机" << endl;
}
};
class HeroB : public AbstractHero {
public:
HeroB() {
cout << "英雄B在打Boss" << endl;
}
virtual void Update() {
cout << "英雄B待机" << endl;
}
};
//观察目标抽象
class AbstractBoss {
public:
//添加观察者
virtual void addHero(AbstractHero* hero) = 0;
//删除观察者
virtual void deleteHero(AbstractHero* hero) = 0;
//通知观察者
virtual void notify() = 0;
};
//具体的观察者 BossA
class BossA : public AbstractBoss {
public:
virtual void addHero(AbstractHero* hero) {
pHeroList.push_back(hero);
}
virtual void deleteHero(AbstractHero* hero) {
pHeroList.remove(hero);
}
virtual void notify() {
for (auto it = pHeroList.begin(); it != pHeroList.end(); ++it) {
(*it)->Update();
}
}
private:
list<AbstractHero*> pHeroList;
};
int main() {
//创建具体观察者
AbstractHero* heroA = new HeroA;
AbstractHero* heroB = new HeroB;
//创建观察目标
AbstractBoss* bossA = new BossA;
bossA->addHero(heroA);
bossA->addHero(heroB);
cout << "heroA阵亡" << endl;
bossA->deleteHero(heroA);
cout << "BOSS被打败了,通知英雄停止攻击,抢装备" << endl;
bossA->notify();
}
总结
- 使用面向对象的抽象,Observer模式使得我们可以独立地改变目标与观察者,从而使二者之间的依赖关系达致松耦合
- 目标发送通知时,无需指定观察者,通知(可以携带通知信息作为参数)会自动传播
- 观察者自己决定是否需要订阅通知,目标对象对此一无所知
- Observer模式是基于事件的UI框架中非常常用的设计模式,也是MVC模式的一个重要组成部分
装饰模式
动机
在某些情况下我们可能会“过度地使用继承来扩展对象的功能”,由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能的组合)会导致更多子类的膨胀。
模式定义
动态(组合)地给一个对象增加一些额外的职责。就增加功能而言,Decorator模式比继承更为灵活(消除重复代码 & 减少子类个数)
普通代码
class Stream{
public:
virtual char Read(int number)=0;
virtual void Seek(int position)=0;
virtual void Write(char data)=0;
virtual ~Stream(){}
};
//主体类
class FileStream: public Stream{
public:
virtual char Read(int number){
//读文件流
}
virtual void Seek(int position){
//定位文件流
}
virtual void Write(char data){
//写文件流
}
};
class NetworkStream :public Stream{
public:
virtual char Read(int number){
//读网络流
}
virtual void Seek(int position){
//定位网络流
}
virtual void Write(char data){
//写网络流
}
};
class MemoryStream :public Stream{
public:
virtual char Read(int number){
//读内存流
}
virtual void Seek(int position){
//定位内存流
}
virtual void Write(char data){
//写内存流
}
};
//扩展操作
class CryptoFileStream :public FileStream{
public:
virtual char Read(int number){
//额外的加密操作...
FileStream::Read(number);//读文件流
}
virtual void Seek(int position){
//额外的加密操作...
FileStream::Seek(position);//定位文件流
//额外的加密操作...
}
virtual void Write(byte data){
//额外的加密操作...
FileStream::Write(data);//写文件流
//额外的加密操作...
}
};
class CryptoNetworkStream : :public NetworkStream{
public:
virtual char Read(int number){
//额外的加密操作...
NetworkStream::Read(number);//读网络流
}
virtual void Seek(int position){
//额外的加密操作...
NetworkStream::Seek(position);//定位网络流
//额外的加密操作...
}
virtual void Write(byte data){
//额外的加密操作...
NetworkStream::Write(data);//写网络流
//额外的加密操作...
}
};
class CryptoMemoryStream : public MemoryStream{
public:
virtual char Read(int number){
//额外的加密操作...
MemoryStream::Read(number);//读内存流
}
virtual void Seek(int position){
//额外的加密操作...
MemoryStream::Seek(position);//定位内存流
//额外的加密操作...
}
virtual void Write(byte data){
//额外的加密操作...
MemoryStream::Write(data);//写内存流
//额外的加密操作...
}
};
class BufferedFileStream : public FileStream{
//...
};
class BufferedNetworkStream : public NetworkStream{
//...
};
class BufferedMemoryStream : public MemoryStream{
//...
}
class CryptoBufferedFileStream :public FileStream{
public:
virtual char Read(int number){
//额外的加密操作...
//额外的缓冲操作...
FileStream::Read(number);//读文件流
}
virtual void Seek(int position){
//额外的加密操作...
//额外的缓冲操作...
FileStream::Seek(position);//定位文件流
//额外的加密操作...
//额外的缓冲操作...
}
virtual void Write(byte data){
//额外的加密操作...
//额外的缓冲操作...
FileStream::Write(data);//写文件流
//额外的加密操作...
//额外的缓冲操作...
}
};
void Process(){
//编译时装配
CryptoFileStream *fs1 = new CryptoFileStream();
BufferedFileStream *fs2 = new BufferedFileStream();
CryptoBufferedFileStream *fs3 =new CryptoBufferedFileStream();
}
装饰模式代码
class Stream{
public:
virtual char Read(int number)=0;
virtual void Seek(int position)=0;
virtual void Write(char data)=0;
virtual ~Stream(){}
};
//主体类
class FileStream: public Stream{
public:
virtual char Read(int number){
//读文件流
}
virtual void Seek(int position){
//定位文件流
}
virtual void Write(char data){
//写文件流
}
};
class NetworkStream :public Stream{
public:
virtual char Read(int number){
//读网络流
}
virtual void Seek(int position){
//定位网络流
}
virtual void Write(char data){
//写网络流
}
};
class MemoryStream :public Stream{
public:
virtual char Read(int number){
//读内存流
}
virtual void Seek(int position){
//定位内存流
}
virtual void Write(char data){
//写内存流
}
};
//扩展操作
DecoratorStream: public Stream{
protected:
Stream* stream;//new FileStream()...,运行时动态绑定
DecoratorStream(Stream * stm):stream(stm){
}
};
class CryptoStream: public DecoratorStream {
public:
CryptoStream(Stream* stm):DecoratorStream(stm){
}
virtual char Read(int number){
//额外的加密操作...
stream->Read(number);//读文件流
}
virtual void Seek(int position){
//额外的加密操作...
stream::Seek(position);//定位文件流
//额外的加密操作...
}
virtual void Write(byte data){
//额外的加密操作...
stream::Write(data);//写文件流
//额外的加密操作...
}
};
class BufferedStream : public DecoratorStream{
Stream* stream;//...
public:
BufferedStream(Stream* stm):DecoratorStream(stm){
}
//...
};
void Process(){
//运行时装配
FileStream* s1=new FileStream();
CryptoStream* s2=new CryptoStream(s1);
BufferedStream* s3=new BufferedStream(s1);
BufferedStream* s4=new BufferedStream(s2);
}
总结
- 通过采用组合而非继承的手法, Decorator模式实现了在运行时动态扩展对象功能的能力,而且可以根据需要扩展多个功能。避免了使用继承带来的“灵活性差”和“多子类衍生问题”。
- Decorator类在接口上表现为is-a Component的继承关系,即 Decorator类继承了Component类所具有的接口。但在实现上又 表现为has-a Component的组合关系,即Decorator类又使用了 另外一个Component类
- Decorator模式的目的并非解决“多子类衍生的多继承”问题, Decorator模式应用的要点在于解决“主体类在多个方向上的扩展 功能”——是为“装饰”的含义。
桥模式
动机
由于某些类型的固有的实现逻辑,使得它们具有两个变化的维度,乃至多个纬度的变化。如何应对这种“多维度的变化”?如何利用面向对象技术来使得类型可以轻松地沿着两个乃至多个方向变化,而不引入额外的复杂度。
模式定义
将抽象部分(业务功能)与实现部分(平台实现)分离,使它们都可以独立地变化
普通实现代码
class Messager{
public:
virtual void Login(string username, string password)=0;
virtual void SendMessage(string message)=0;
virtual void SendPicture(Image image)=0;
virtual void PlaySound()=0;
virtual void DrawShape()=0;
virtual void WriteText()=0;
virtual void Connect()=0;
virtual ~Messager(){}
};
//平台实现
class PCMessagerBase : public Messager{
public:
virtual void PlaySound(){
//**********
}
virtual void DrawShape(){
//**********
}
virtual void WriteText(){
//**********
}
virtual void Connect(){
//**********
}
};
class MobileMessagerBase : public Messager{
public:
virtual void PlaySound(){
//==========
}
virtual void DrawShape(){
//==========
}
virtual void WriteText(){
//==========
}
virtual void Connect(){
//==========
}
};
//业务抽象
class PCMessagerLite : public PCMessagerBase {
public:
virtual void Login(string username, string password){
PCMessagerBase::Connect();
//........
}
virtual void SendMessage(string message){
PCMessagerBase::WriteText();
//........
}
virtual void SendPicture(Image image){
PCMessagerBase::DrawShape();
//........
}
};
class PCMessagerPerfect : public PCMessagerBase {
public:
virtual void Login(string username, string password){
PCMessagerBase::PlaySound();
//********
PCMessagerBase::Connect();
//........
}
virtual void SendMessage(string message){
PCMessagerBase::PlaySound();
//********
PCMessagerBase::WriteText();
//........
}
virtual void SendPicture(Image image){
PCMessagerBase::PlaySound();
//********
PCMessagerBase::DrawShape();
//........
}
};
class MobileMessagerLite : public MobileMessagerBase {
public:
virtual void Login(string username, string password){
MobileMessagerBase::Connect();
//........
}
virtual void SendMessage(string message){
MobileMessagerBase::WriteText();
//........
}
virtual void SendPicture(Image image){
MobileMessagerBase::DrawShape();
//........
}
};
class MobileMessagerPerfect : public MobileMessagerBase {
public:
virtual void Login(string username, string password){
MobileMessagerBase::PlaySound();
//********
MobileMessagerBase::Connect();
//........
}
virtual void SendMessage(string message){
MobileMessagerBase::PlaySound();
//********
MobileMessagerBase::WriteText();
//........
}
virtual void SendPicture(Image image){
MobileMessagerBase::PlaySound();
//********
MobileMessagerBase::DrawShape();
//........
}
};
桥接模式代码
class Messager{
protected:
MessagerImp* messagerImp;//...
public:
virtual void Login(string username, string password)=0;
virtual void SendMessage(string message)=0;
virtual void SendPicture(Image image)=0;
virtual ~Messager(){}
};
class MessagerImp{
public:
virtual void PlaySound()=0;
virtual void DrawShape()=0;
virtual void WriteText()=0;
virtual void Connect()=0;
virtual MessagerImp(){}
};
//平台实现 n
class PCMessagerImp : public MessagerImp{
public:
virtual void PlaySound(){
//**********
}
virtual void DrawShape(){
//**********
}
virtual void WriteText(){
//**********
}
virtual void Connect(){
//**********
}
};
class MobileMessagerImp : public MessagerImp{
public:
virtual void PlaySound(){
//==========
}
virtual void DrawShape(){
//==========
}
virtual void WriteText(){
//==========
}
virtual void Connect(){
//==========
}
};
//业务抽象 m
//类的数目:1+n+m
class MessagerLite :public Messager {
public:
virtual void Login(string username, string password){
messagerImp->Connect();
//........
}
virtual void SendMessage(string message){
messagerImp->WriteText();
//........
}
virtual void SendPicture(Image image){
messagerImp->DrawShape();
//........
}
};
class MessagerPerfect :public Messager {
public:
virtual void Login(string username, string password){
messagerImp->PlaySound();
//********
messagerImp->Connect();
//........
}
virtual void SendMessage(string message){
messagerImp->PlaySound();
//********
messagerImp->WriteText();
//........
}
virtual void SendPicture(Image image){
messagerImp->PlaySound();
//********
messagerImp->DrawShape();
//........
}
};
总结
- Bridge模式使用“对象间的组合关系”解耦了抽象和实现之间固 有的绑定关系,使得抽象和实现可以沿着各自的维度来变化。所谓抽象和实现沿着各自纬度的变化,即“子类化”它们。
- Bridge模式有时候类似于多继承方案,但是多继承方案往往违背 单一职责原则(即一个类只有一个变化的原因),复用性比较差。Bridge模式是比多继承方案更好的解决方法
- Bridge模式的应用一般在“两个非常强的变化维度”,有时一个 类也有多于两个的变化维度,这时可以使用Bridge的扩展