11.3.4模板模式
模板模式:定义一个操作中的算法骨架,将一些步骤延迟到子类中。模板模式使得子类可以不改变一个算法的接口即可重定义该算法的某些特定步骤。
模板模式是行为型模式中最简单的一种,在实际应用中会经常使用。注:模板模式和前面的类/函数模板不同。
案例:现在公司组2个队伍,一个队伍打羽毛球,一个队伍打篮球,请完成这个程序的设计。
#include <iostream>
using namespace std;
class Sport
{
protected:
virtual bool organizeTeam(void) = 0;
virtual bool prepareEquipment(void) = 0;
public:
virtual void startGame(void) = 0;
};
class Basketball:public Sport
{
protected:
bool organizeTeam(void)
{
cout << "篮球队5人组队完成" << endl;
return 1;
}
bool prepareEquipment(void)
{
cout << "篮球已准备好" << endl;
return 1;
}
public:
void startGame(void)
{
if (organizeTeam() && prepareEquipment())
cout << "开始篮球比赛" << endl;
}
};
class Badminton :public Sport
{
protected:
bool organizeTeam(void)
{
cout << "羽毛球队2人组队完成" << endl;
return 1;
}
bool prepareEquipment(void)
{
cout << "羽毛球拍和羽毛球已准备好" << endl;
return 1;
}
public:
void startGame(void)
{
if (organizeTeam() && prepareEquipment())
cout << "开始羽毛球比赛" << endl;
}
};
int main(int argc, char ** argv)
{
Basketball bas;
bas.startGame();
Badminton badm;
badm.startGame();
return 0;
}
运行结果:
篮球队5人组队完成
篮球已准备好
开始篮球比赛
羽毛球队2人组队完成
羽毛球拍和羽毛球已准备好
开始羽毛球比赛
模板模式结构图:
AbstractClass:抽象类,定义算法的框架。
ConcreteClass:具体类,实现框架中的算法。
11.4结构型模式
结构型模式:通过不同类、对象的组合,来简化设计。结构型设计模式的准则:多用组合,少用继承。主要讲适配器模式、桥接模式、装饰者模式、组合模式、外观模式、代理模式。
11.4.1适配器模式
适配器模式:将一个类的接口转换成客户希望的另一个接口,使得原本不兼容的接口可以正常工作。适配器模式分为2种:类的适配器,对象适配器(常用)。
案例:你在机场候机时,手机电量不足需要充电,但是机场只有三孔的插座,而你的充电器是两脚充电器,因此需要一个三脚的排插才可以充电。请完成这个程序的设计。
//类的适配器:多继承方式
#include <iostream>
using namespace std;
//三孔插座
class ThreeSocket
{
public:
virtual ~ThreeSocket() {}
virtual void Charge(void)
{
cout << "连接三脚充电器..." << endl;
}
};
//双脚充电器
class TwoCharger
{
public:
virtual ~TwoCharger() {}
void startCharge()
{
cout << "开始充电" << endl;
}
};
//适配器:三脚排插
class ThreeIntercalation:public ThreeSocket,public TwoCharger
{
public:
virtual void Charge(void)
{
startCharge();
}
};
int main(int argc, char ** argv)
{
ThreeIntercalation ti;
ti.Charge();
return 0;
}
//对象适配器:对象组合方式
#include <iostream>
using namespace std;
//三孔插座
class ThreeSocket
{
public:
virtual ~ThreeSocket() {}
virtual void Charge(void)
{
cout << "连接三脚充电器..." << endl;
}
};
//双脚充电器
class TwoCharger
{
public:
virtual ~TwoCharger() {}
void startCharge()
{
cout << "开始充电" << endl;
}
};
//适配器:三脚排插
class ThreeIntercalation:public ThreeSocket
{
private:
TwoCharger * tc;
public:
virtual void Charge(void)
{
tc->startCharge();
}
};
int main(int argc, char ** argv)
{
ThreeIntercalation ti;
ti.Charge();
return 0;
}
运行结果:
开始充电
类适配器结构图:
对象适配器结构图:
Target:目标接口,相当于三孔插座;
Adaptee:适配者,相当于双脚充电器;
Adapter:适配器,相当于三脚排插。
11.4.2桥接模式
桥接模式:将抽象部份与它的实现部份分离,使它们都可以独立地变化。举例:给手机(华为,苹果)安装软件(微信,QQ)。代码如下:
#include <iostream>
using namespace std;
class Phone
{
public:
virtual void PhoneType(void) = 0;
};
class Huawei:public Phone
{
public:
void PhoneType(void)
{
cout << "华为手机" << endl;
}
};
class Apple :public Phone
{
public:
void PhoneType(void)
{
cout << "苹果手机" << endl;
}
};
class Software
{
public:
virtual void printinfo() = 0;
};
class WeChat:public Software
{
public:
virtual void printinfo()
{
cout << "微信" << endl;
}
};
class QQ:public Software
{
public:
virtual void printinfo()
{
cout << "QQ" << endl;
}
};
class HuaweiWithWeChat :public Huawei,public WeChat
{
public:
void InstallSoftware(void)
{
cout << "华为手机开始安装微信" << endl;
}
};
class HuaweiWithQQ :public Huawei, public QQ
{
public:
void InstallSoftware(void)
{
cout << "华为手机开始安装微信" << endl;
}
};
class AppleWithWeChat :public Apple, public WeChat
{
public:
void InstallSoftware(void)
{
cout << "苹果手机开始安装微信" << endl;
}
};
class AppleWithQQ :public Apple, public QQ
{
public:
void InstallSoftware(void)
{
cout << "苹果手机开始安装QQ" << endl;
}
};
int main(int argc, char ** argv)
{
HuaweiWithWeChat hwc;
hwc.InstallSoftware();
return 0;
}
通过这样的方式来编写代码,产生了太多的派生类,因此采用桥接模式。
#include <iostream>
using namespace std;
class Phone
{
public:
virtual void PhoneType(void) = 0;
};
class Huawei:public Phone
{
public:
void PhoneType(void)
{
cout << "华为手机" << endl;
}
};
class Apple :public Phone
{
public:
void PhoneType(void)
{
cout << "苹果手机" << endl;
}
};
class Software
{
public:
virtual void printinfo() = 0;
};
class WeChat:public Software
{
public:
virtual void printinfo()
{
cout << "微信" << endl;
}
};
class QQ:public Software
{
public:
virtual void printinfo()
{
cout << "QQ" << endl;
}
};
class HuaweiInstall:public Huawei
{
private:
Software * sw;
public:
HuaweiInstall(Software * sw):sw(sw)
{}
~HuaweiInstall() {}
void InstallSoftware(void)
{
cout << "华为手机开始安装软件" << endl;
}
};
class AppleInstall :public Apple
{
private:
Software * sw;
public:
AppleInstall(Software * sw) :sw(sw)
{}
~AppleInstall() {}
void InstallSoftware(void)
{
cout << "苹果手机开始安装软件" << endl;
}
};
int main(int argc, char ** argv)
{
WeChat * wec = new WeChat;
HuaweiInstall hi(wec);
hi.InstallSoftware();
delete wec;
return 0;
}
运行结果:
华为手机开始安装软件
桥接模式的本质是将多继承方式转换为对象组合方式。这种方式减少了派生类的产生,便于代码的设计。
桥接模式结构图:
11.4.3装饰者模式
装饰者模式:在不改变原类文件和继承的情况下,动态的扩展一个对象的功能。
案例:日常使用的手机种类很多,有华为手机、苹果手机等,若我们想要给手机配上手机壳、挂件、耳机等,那该如何实现。
#include <iostream>
#include <string>
using namespace std;
class Phone
{
public:
~Phone() {}
virtual string pName(void) = 0;
};
class Huawei:public Phone
{
public:
~Huawei() {}
virtual string pName(void)
{
return "Huawei";
}
};
class Apple :public Phone
{
public:
~Apple() {}
virtual string pName(void)
{
return "Apple";
}
};
//装饰品
class PhoneDecorator :public Phone
{
protected:
Phone * pPho;
public:
PhoneDecorator(Phone * pPho) :pPho(pPho) {}
~PhoneDecorator() {}
virtual string pName(void)
{
return pPho->pName() + " PhoneDecorator";
}
};
//手机壳
class PhoneShell :public PhoneDecorator
{
public:
PhoneShell(Phone * pPho) :PhoneDecorator(pPho) {}
~PhoneShell() {}
virtual string pName(void)
{
return pPho->pName() + " PhoneShell";
}
};
//手机挂机
class PhonePendant :public PhoneDecorator
{
public:
PhonePendant(Phone * pPho) :PhoneDecorator(pPho) {}
~PhonePendant() {}
virtual string pName(void)
{
return pPho->pName() + " PhonePendant";
}
};
//手机耳机
class PhoneHeadset :public PhoneDecorator
{
public:
PhoneHeadset(Phone * pPho) :PhoneDecorator(pPho) {}
~PhoneHeadset() {}
virtual string pName(void)
{
return pPho->pName() + " PhoneHeadset";
}
};
int main(int argc, char ** argv)
{
//华为手机
Huawei * hw = new Huawei;
//华为手机+手机壳
PhoneDecorator * ps = new PhoneShell(hw);
cout << ps->pName() << endl;
//华为手机+手机壳+挂机
PhoneDecorator * ph = new PhonePendant(ps);
cout << ph->pName() << endl;
delete hw;
delete ps;
delete ph;
return 0;
}
运行结果:
Huawei PhoneShell
Huawei PhoneShell PhonePendant
装饰者模式结构图:
Component:抽象组件;
ConcreteComponent:具体组件;
Decorator:抽象装饰品;
ConcreteDecorator:具体装饰品。
11.4.4外观模式
外观模式:为子系统中的一组接口提供一个统一的高层接口,该接口使子系统的使用更加简单方便。
在vs中点击编译,在编译器内部分为4个步骤:预处理、编译、汇编、链接。
#include <iostream>
using namespace std;
class Pretreatment
{
public:
void Run(void)
{
cout << "Pretreatment" << endl;
}
};
class Compile
{
public:
void Run(void)
{
cout << "Compile" << endl;
}
};
class Assemble
{
public:
void Run(void)
{
cout << "Assemble" << endl;
}
};
class Link
{
public:
void Run(void)
{
cout << "Link" << endl;
}
};
class CompileInterface
{
private:
Pretreatment pre;
Compile com;
Assemble ass;
Link li;
public:
void Run(void)
{
pre.Run();
com.Run();
ass.Run();
li.Run();
}
};
int main(int argc, char ** argv)
{
CompileInterface ci;
ci.Run();
return 0;
}
运行结果:
Pretreatment
Compile
Assemble
Link
外观模式结构图:
Facade:外观;Subsystem:子系统。
11.4.5组合模式
组合模式:将对象组合成树状结构来表示“整体-部分”层次结构。
实例:一个公司,有自己直属的财务部、工程部,它的整个结构就是一个树形结构。
#include <iostream>
#include <string>
#include <list>
using namespace std;
class Company
{
public:
virtual ~Company() {}
virtual void printinfo(void) = 0;
};
//具体公司
class ConcreteCompany:public Company
{
private:
string name;
list<Company *> pCompanys;
public:
ConcreteCompany(string name) :name(name) {}
virtual ~ConcreteCompany() {}
void AddCompany(Company * comp)
{
pCompanys.push_back(comp);
}
void DeleteCompany(Company * comp)
{
pCompanys.remove(comp);
}
void printinfo(void)
{
cout << name << endl;
for (list<Company *>::iterator it = pCompanys.begin(); it != pCompanys.end(); ++it)
{
(*it)->printinfo();
}
}
};
//具体部门
class ConcreteDepartment :public Company
{
private:
string name;
public:
ConcreteDepartment(string name) :name(name) {}
virtual ~ConcreteDepartment() {}
void printinfo(void)
{
cout << name << endl;
}
};
int main(int argc, char ** argv)
{
ConcreteCompany * head_office = new ConcreteCompany("总公司");
Company * finance = new ConcreteDepartment("财务部");
Company * engineering = new ConcreteDepartment("工程部");
head_office->AddCompany(finance);
head_office->AddCompany(engineering);
head_office->printinfo();
cout << "删除工程部:" << endl;
head_office->DeleteCompany(engineering);
head_office->printinfo();
return 0;
}
运行结果:
总公司
财务部
工程部
删除工程部:
总公司
财务部
组合模式结构图:
Component:抽象组件,相当于代码中的Company类;
Composite:容器组件,相当于代码中的ConcreteCompany类;
Leaf:叶子组件,相当于代码中的ConcreteDepartment类。
组合模式分为透明组合模式和安全组合模式。透明组合模式是在Component中定义用于管理和访问容器、叶子组件的接口,优点是可以确保所有组件都有相同的接口。安全组合模式是在Component中不定义任何管理和访问容器、叶子组件的接口,而在Composite中实现。
11.4.6代理模式
代理模式:为其他对象提供一种代理,以控制这个对象的访问。代理对象在客户和目标对象之间起到中介的作用。
实例:苹果的A12芯片由台积电代工。
#include <iostream>
using namespace std;
class A12chip
{
public:
virtual void printinfo(void) = 0;
virtual ~A12chip() {}
};
class Apple:public A12chip
{
public:
virtual void printinfo(void)
{
cout << "A12chip" << endl;
}
virtual ~Apple() {}
};
class TSMC :public A12chip
{
private:
Apple * pApple;
public:
TSMC(Apple * pApple) :pApple(pApple) {}
virtual void printinfo(void)
{
pApple->printinfo();
}
virtual ~TSMC() {}
};
int main(int argc, char ** argv)
{
Apple * pApple = new Apple;
TSMC tsmc(pApple);
tsmc.printinfo();
delete pApple;
return 0;
}
运行结果:
A12chip
代理模式结构图:
Subject:抽象角色;Realsubject:真实角色;Proxy:代理角色。