1. 设计模式三原则
在进行程序设计的时候,要尽可能地保证程序的可扩展性、可维护性和可读性,所以需要使用一些设计模式,这些设计模式都遵循了以下三个原则。
1.1 单一职责原则
C++面向对象三大特性之一的封装
指的就是将单一事物抽象出来组合成一个类,所以我们在设计类的时候每个类中处理的是单一事物而不是某些事物的集合。
设计模式中所谓的单一职责原则:就是对一个类而言,应该仅有一个引起它变化的原因,其实就是将这个类所承担的职责单一化。
1.2 开放封闭原则
开放封闭原则:指的是软件实体(类、模块、函数等)可以扩展,但是不可以修改。也就是说对于扩展是开放的,对于修改是封闭的。
开放封闭原则是面向对象设计的核心所在,这样可以给我们设计出的程序带来巨大的好处,使其可维护性、可扩展性、可复用性、灵活性更好。
1.3 依赖倒转原则
关于依赖倒转原则,对应的是两条非常抽象的描述:
- 高层模块不应该依赖低层模块,两个都应该依赖抽象。
- 高层模块:可以理解为上层应用,就是业务层的实现
- 低层模块:可以理解为底层接口,比如封装好的API、动态库等
- 抽象:指的就是抽象类或者接口,在C++中没有接口,只有抽象类
- 抽象不应该依赖细节,细节应该依赖抽象。
- 里氏代换原则:就是子类类型必须能够替换掉它们的父类类型。
2. 单例模式
在一个项目中,全局范围内,某个类的实例有且仅有一个,通过这个唯一实例向其他模块提供数据的全局访问,这种模式就叫单例模式
。单例模式的典型应用就是任务队列。
在实现一个单例模式的类的时候,有两种处理模式:
2.1 饿汉模式
饿汉模式:定义类的时候就创建了单例实例,创建出来后,什么时候用,时候什么就调用静态的成员函数(得到单例对象)。
缺点:浪费空间
优点:在多线程的场景下,饿汉模式是没有线程安全问题的(多线程可以同时访问这个单例的对象)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| class TaskQueue { public: TaskQueue(const TaskQueue& t) = delete; TaskQueue& operator = (const TaskQueue& t) = delete; static TaskQueue* getInstance() { return m_taskQ; } void print() { cout << "我是单例对象的一个成员函数..." << endl; }
private: TaskQueue() = default; static TaskQueue* m_taskQ; };
TaskQueue* TaskQueue::m_taskQ = new TaskQueue;
int main(){ TaskQueue* taskQ = TaskQueue::getInstance(); taskQ->print(); }
|
2.2 懒汉模式
懒汉模式:什么时候使用这个单例对象,在使用的时候再去创建对应的实例。
优点:节省空间
缺点:在多线程的场景下,懒汉模式是有线程安全问题的(若干个线程同时访问单例的实例,会出问题)。
- 解决办法:通过互斥锁,阻塞线程,依次访问这个单例对象,就可以避免在懒汉模式下,多线程同时访问单例对象而创建出多了类的实例这种问题
双重检查锁定:如果没有第9行的判断,该方法对程序执行的效率就很低,因为不管什么时候,多个线程在访问单例对象的时候(执行getInstance()函数),都是顺序访问的。但通过双重检查锁定可以解决这个问题,只有第一次的时候,多个线程是线性访问,当后面再访问该函数时(m_taskQ指针被实例化处理之后),多个线程就是并行访问了,因为第9行代码判断为false,直接返回该实例对象即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| class TaskQueue { public: TaskQueue(const TaskQueue& obj) = delete; TaskQueue& operator=(const TaskQueue& obj) = delete; static TaskQueue* getInstance() { if (m_taskQ == nullptr) { m_mutex.lock(); if (m_taskQ == nullptr) { m_taskQ = new TaskQueue; } m_mutex.unlock(); } return m_taskQ; } private: TaskQueue() = default; static TaskQueue* m_taskQ; static mutex m_mutex; }; TaskQueue* TaskQueue::m_taskQ = nullptr; mutex TaskQueue::m_mutex;
|
上面程序第14行代码对应的机器指令有3条,第1条是创建一块内存(无数据);第2条是创建TaskQueue对象,并吧数据写入到创建的内存里面;第3条是将创建的有效地址传给m_taskQ指针。在底层执行程序的时候,可能会对这些指令做重排,就有可能是执行的顺序是132,在还没有执行第2条时,就先将内存地址传给了指针,这时的指针不为空,但没有TaskQueue对象,同一时刻的其它线程调用该函数就会直接返回指针使用,就造成了系统崩溃。所以下面可以通过原子变量来解决这个问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| class TaskQueue { public: TaskQueue(const TaskQueue& t) = delete; TaskQueue& operator = (const TaskQueue& t) = delete; static TaskQueue* getInstance() { TaskQueue* task = m_taskQ.load(); if (task == nullptr) { m_mutex.lock(); task = m_taskQ.load(); if (task == nullptr) { task = new TaskQueue; m_taskQ.store(task); } m_mutex.unlock(); } return task; } void print() { cout << "我是单例对象的一个成员函数..." << endl; }
private: TaskQueue() = default; static mutex m_mutex; static atomic<TaskQueue*>m_taskQ; };
atomic<TaskQueue*> TaskQueue::m_taskQ; mutex TaskQueue::m_mutex;
|
当然,也可以使用静态的局部对象解决线程安全问题。
3. 工厂模式
3.1 简单工厂模式
下面程序就是简单工厂模式
实现的例子,首先创建一个产品类作为父类,里面只需要定义一些虚函数即可,供子类继承实现。然后创建一个工厂类,里面实现父类指针指向子类对象,以达到多态的效果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
| class AbstractSmile { public: virtual void transform() = 0; virtual void ability() = 0; virtual ~AbstractSmile() {} };
class SheepSmile :public AbstractSmile { public: void transform() override { cout << "变成人兽 -- 山羊人形态..." << endl; } void ability() override { cout << "将手臂变成绵羊角的招式--巨羊角" << endl; } };
class LionSmile :public AbstractSmile { public: void transform() override { cout << "变成人兽 -- 狮子人形态..." << endl; } void ability() override { cout << "火遁 -- 豪火球之术..." << endl; } };
class BatSmile :public AbstractSmile { public: void transform() override { cout << "变成人兽 -- 蝙蝠人形态..." << endl; } void ability() override { cout << "声纳-引剑之万归宗..." << endl; } };
enum class Type :char {Sheep,Lion,Bat}; class SmileFactory{ public: AbstractSmile* createSmile(Type type){ AbstractSmile* ptr = nullptr; switch (type) { case Type::Sheep: ptr = new SheepSmile; break; case Type::Lion: ptr = new LionSmile; break; case Type::Bat: ptr = new BatSmile; break; default: break; } return ptr; } };
int main(){ SmileFactory factory; AbstractSmile* obj = factory.createSmile(Type::Lion); obj->transform(); obj->ability(); }
|
3.2 工厂模式
在上面的简单工厂模式中是只创建了一个工厂类,用于生产需要的对象,但是这种方式有一个弊端,它违反了设计模式中的开放封闭原则,即如果想要生成更多的人造恶魔果实,那么就需要在工厂函数的switch语句中添加更多的case,很明显这违背了封闭原则。所以我们可以使用工厂模式很完美的解决上述的问题。总的来说,就是简单工厂模式是只有一个工厂类,而工厂模式是有很多的工厂类:
- 一个基类,包含一个虚工厂函数,用于实现多态。
- 多个子类,重写父类的工厂函数。每个子工厂类负责生产一种恶魔果实,这相当于再次解耦,将工厂类的职责再次拆分、细化,如果要生产新品种的恶魔果实,那么只需要添加对应的工厂类,无需修改原有的代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
|
class AbstractSmile { public: virtual void transform() = 0; virtual void ability() = 0; virtual ~AbstractSmile() {} };
class SheepSmile :public AbstractSmile { public: void transform() override { cout << "变成人兽 -- 山羊人形态..." << endl; } void ability() override { cout << "将手臂变成绵羊角的招式 -- 巨羊角" << endl; } };
class LionSmile :public AbstractSmile { public: void transform() override { cout << "变成人兽 -- 狮子人形态..." << endl; } void ability() override { cout << "火遁 -- 豪火球之术..." << endl; } };
class BatSmile :public AbstractSmile { public: void transform() override { cout << "变成人兽 -- 蝙蝠人形态..." << endl; } void ability() override { cout << "声纳-引剑之万归宗..." << endl; } };
class AbstractFactory { public: virtual AbstractSmile* createSmile() = 0; virtual ~AbstractFactory() {} };
class SheepFactory : public AbstractFactory { public: AbstractSmile* createSmile() { return new SheepSmile; } ~SheepFactory() { cout << "SheppFactory被析构了..." << endl; } };
class LionFactory : public AbstractFactory { public: AbstractSmile* createSmile() { return new LionSmile; } ~LionFactory() { cout << "LionFactory被析构了..." << endl; } };
class BatFactory : public AbstractFactory { public: AbstractSmile* createSmile() { return new BatSmile; } ~BatFactory() { cout << "BatFactory被析构了..." << endl; } };
int main() { AbstractFactory* factory = new LionFactory; AbstractSmile* obj = factory->createSmile(); obj->transform(); obj->ability(); delete obj; delete factory; return 0; }
|
3.3 抽象工厂模式
抽象工厂模式
适用于比较复杂的多变的业务场景,总体上就是给一系列功能相同但是属性会发生变化的组件(如:船体材料、武器系统、动力系统)添加一个抽象类,这样就可以非常方便地进行后续的拓展,再搭配工厂类就可以创建出我们需要的对象了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
| class ShipBody { public: virtual string getBody() = 0; virtual ~ShipBody() {} };
class WoodBody :public ShipBody { public: string getBody() override { return string("使用<木材>制作海贼船的船体..."); } };
class IronBody :public ShipBody { public: string getBody() override { return string("使用<钢铁>制作海贼船的船体..."); } };
class MetalBody :public ShipBody { public: string getBody() override { return string("使用<合成金属>制作海贼船的船体..."); } };
class Engine { public: virtual string getEngine() = 0; virtual ~Engine() {} };
class Human :public Engine { public: string getEngine() { return "海贼船的动力方式是<手动>..."; } };
class Diesel :public Engine { public: string getEngine() { return "海贼船的动力方式是<内燃机>..."; } };
class Nuclear :public Engine { public: string getEngine() { return "海贼船的动力方式是<核反应堆>..."; } };
class Weapon { public: virtual string getWeapon() = 0; virtual ~Weapon() {} };
class Gun : public Weapon { public: string getWeapon() { return string("船上的武器系统是<枪>..."); } };
class Cannon : public Weapon { public: string getWeapon() { return string("船上的武器系统是<加农跑>..."); } };
class Laser : public Weapon { public: string getWeapon() { return string("船上的武器系统是<激光>..."); } };
class Ship { public: Ship(ShipBody* body, Engine* engine, Weapon* weapon) : m_body(body), m_engine(engine), m_weapon(weapon) {} ~Ship() { delete m_body; delete m_weapon; delete m_engine; } string getProperty() { string info = m_body->getBody() + m_weapon->getWeapon() + m_engine->getEngine(); return info; }
private: ShipBody* m_body; Engine* m_engine; Weapon* m_weapon; };
class AbstractFactory { public: virtual Ship* createShip() = 0; virtual ~AbstractFactory() {} };
class BasicFactory :public AbstractFactory { public: Ship* createShip() override { Ship* ship = new Ship(new WoodBody, new Human, new Gun); cout << "<基础型的海贼船> 已经建造完毕!!!" << endl; return ship; } };
class StandardFactory :public AbstractFactory { public: Ship* createShip() override { Ship* ship = new Ship(new IronBody, new Diesel, new Cannon); cout << "<标准型的海贼船> 已经建造完毕!!!" << endl; return ship; } };
class UltimataFactory :public AbstractFactory { public: Ship* createShip() override { Ship* ship = new Ship(new MetalBody, new Nuclear, new Laser); cout << "<旗舰型的海贼船> 已经建造完毕!!!" << endl; return ship; } };
int main() { AbstractFactory* factory = new UltimataFactory; Ship* ship = factory->createShip(); cout << ship->getProperty() << endl; delete ship; delete factory; return 0; }
|
最后对简单工厂模式
、工厂模式
和抽象工厂模式
的区别做如下总结:
- 简单工厂模式不能遵守开放封闭原则,工厂和抽象工厂模式可以
- 简单工厂模式只有一个工厂类,工厂和抽象工厂有多个工厂类
- 工厂模式创建的产品对象相对简单,抽象工厂模式创建的产品对象相对复杂
- 工厂模式创建的对象对应的类不需要提供抽象类(这产品类组件中没有可变因素)
- 抽象工厂模式创建的对象对应的类有抽象的基类(这个产品类组件中有可变因素)
4. 建造者(生成器)模式
下面程序为创造模式的一个例子。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
| class SunnyShip { public: void addParts(string name) { m_parts.push_back(name); } void showParts() { for (const auto& item : m_parts) { cout << item << " "; } cout << endl; } private: vector<string> m_parts; };
class MerryShip { public: void assemble(string name, string parts) { m_parts.insert(make_pair(parts,name)); } void showParts() { for (const auto& item : m_parts) { cout << item.first<< ":" << item.second; } cout << endl; } private: map<string, string> m_parts; };
class ShipBuilder { public: virtual void reset() = 0; virtual void buildBody() = 0; virtual void buildWeapon() = 0; virtual void buildEngine() = 0; virtual void buildInterior() = 0; virtual ~ShipBuilder() {} };
class SunnyBuilder :public ShipBuilder { public: SunnyBuilder() { reset(); } void reset()override { m_sunny = new SunnyShip; } SunnyShip* getSunnyShip() { SunnyShip* ship = m_sunny; m_sunny = nullptr; return ship; } void buildBody() override { m_sunny->addParts("船体是神树亚当"); } void buildWeapon() override { m_sunny->addParts("狮吼炮"); } void buildEngine() override { m_sunny->addParts("可乐驱动的内燃机"); } void buildInterior() override { m_sunny->addParts("非常豪华的内室装修"); } ~SunnyBuilder() { if (m_sunny) { delete m_sunny; } } private: SunnyShip* m_sunny; };
class MerryBuilder :public ShipBuilder { public: MerryBuilder() { reset(); } void reset() override { m_merry = new MerryShip; } MerryShip* getMerryShip() { MerryShip* ship = m_merry; m_merry = nullptr; return ship; } void buildBody() override { m_merry->assemble("船体是优质木材","船体"); } void buildWeapon() override { m_merry->assemble("普通的四门大炮","武器系统"); } void buildEngine() override { m_merry->assemble("烧煤的蒸汽机","动力系统"); } void buildInterior() override { m_merry->assemble("非常豪华的内室装修","内室"); } ~MerryBuilder() { if (m_merry) { delete m_merry; } } private: MerryShip* m_merry; };
class Director { public: void setBuilder(ShipBuilder* builder) { m_builder = builder; } void buildSimpleShip() { m_builder->buildBody(); m_builder->buildEngine(); } void buildStandardShip() { buildSimpleShip(); m_builder->buildWeapon(); } void buildRegalShip() { buildStandardShip(); m_builder->buildInterior(); } private: ShipBuilder* m_builder = nullptr; };
void buildSunnyShip() { Director* director = new Director; SunnyBuilder* builder = new SunnyBuilder;
director->setBuilder(builder); director->buildSimpleShip(); SunnyShip* ship = builder->getSunnyShip(); ship->showParts(); delete ship;
builder->reset(); director->buildStandardShip(); ship = builder->getSunnyShip(); ship->showParts(); delete ship;
builder->reset(); director->buildRegalShip(); ship = builder->getSunnyShip(); ship->showParts(); delete ship; delete builder; delete director; }
void buildMerryShip() { Director* director = new Director; MerryBuilder* builder = new MerryBuilder;
director->setBuilder(builder); director->buildSimpleShip(); MerryShip* ship = builder->getMerryShip(); ship->showParts(); delete ship;
builder->reset(); director->buildStandardShip(); ship = builder->getMerryShip(); ship->showParts(); delete ship;
builder->reset(); director->buildRegalShip(); ship = builder->getMerryShip(); ship->showParts(); delete ship; delete builder; delete director; }
int main() { buildMerryShip(); cout << "=============================" << endl; buildSunnyShip(); }
|
5. 原型模式
通过父类指针把对应的子类对象拷贝出来,就是让子类重写了父类提供的克隆函数,然后在每个子类的克隆函数里面调用了子类对应的拷贝构造函数,再通过父类指针指向某一个子类对象,这样就通过指针能够调用某个子类里面的克隆函数了,执行的就是对应子类里面的拷贝动作,这样就能够得到对应的子类实例对象(不是原来那个了)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| class GermaSoldier { public: virtual GermaSoldier* clone() = 0; virtual string whoAmI() = 0; virtual ~GermaSoldier() {} };
class Soldier66 :public GermaSoldier { public: GermaSoldier* clone() override { return new Soldier66(*this); } string whoAmI() override { return "我是soldier66的士兵!!!"; } };
class Soldier67 :public GermaSoldier { public: GermaSoldier* clone() override { return new Soldier67(*this); } string whoAmI() override { return "我是soldier67的士兵!!!"; } };
int main() { GermaSoldier* obj = new Soldier66; GermaSoldier* soldier = obj->clone(); cout << soldier->whoAmI(); delete soldier; delete obj;
obj = new Soldier67; soldier = obj->clone(); cout << soldier->whoAmI(); delete soldier; delete obj; }
|
6.适配器模式
适配器
就是将一个类的接口转换成用户希望的另一个接口,使不兼容的对象能够相互配合并一起工作,这种模式就叫适配器模式。
STL标准模板库有六大组件,其中之一的就是适配器。
- 六大组件分别是:容器、算法、迭代器、仿函数、适配器、空间适配器。
- 适配器又可以分为:容器适配器、函数适配器、迭代器适配器
1.适配器类和熊猫类是关联关系:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
| class Foreigner { public: virtual string confession() = 0; void setResult(string res) { cout << "Panda say: " << res << endl; } virtual ~Foreigner() {} };
class Ammerican : public Foreigner { public: string confession() override { return "我有罪,呼呼呼!!!"; } };
class French : public Foreigner { public: string confession() override { return "我不是人,哎哎哎!!!"; } };
class Panda { public: void recvMessage(string msg) { cout << msg << endl; } string sendMessage() { return string("强盗、凶手,罪人是不可能被宽恕和原谅的!! "); } };
class AbstractChopper { public: AbstractChopper(Foreigner* foreigner) : m_foreigner(foreigner) {} virtual void translateToPanda() = 0; virtual void translateToHuman() = 0; protected: Panda m_panda; Foreigner* m_foreigner; };
class EnglishChopper : public AbstractChopper { public: using AbstractChopper::AbstractChopper; void translateToPanda() { string msg = m_foreigner->confession(); m_panda.recvMessage("美国人说: " + msg); } void translateToHuman() { string msg = m_panda.sendMessage(); m_foreigner->setResult("美国佬: " + msg); } };
class FrechChopper : public AbstractChopper { public: using AbstractChopper::AbstractChopper; void translateToPanda() { string msg = m_foreigner->confession(); m_panda.recvMessage("法国人说: " + msg); } void translateToHuman() { string msg = m_panda.sendMessage(); m_foreigner->setResult("法国佬: " + msg); } };
int main() { Foreigner* foreigner = new Ammerican; AbstractChopper* adapter = new EnglishChopper(foreigner); adapter->translateToPanda(); adapter->translateToHuman(); delete foreigner; delete adapter; cout << "=====================================" << endl; foreigner = new French; adapter = new FrechChopper(foreigner); adapter->translateToPanda(); adapter->translateToHuman(); delete foreigner; delete adapter; }
|
2.适配器类和熊猫类是继承关系:因为熊猫类是没有子类的,所以可以让适配器父类来继承熊猫类,这样在适配器子类中使用熊猫类的recvMessage()
函数和sendMessage()
函数就可以直接使用,而不需要通过m_panda.
来引用。当然,当外国人类也没有子类时,适配器父类就可以继承熊猫类和适配器类(多个类)来实现相应的功能了。
7. 桥接模式
桥接模式
的原则就是将抽象部分和它的实现部分分离,使它们可以独立的变化。
比如说在下面程序中,实现桥接模式的方案:
- 海贼团之间是继承关系,但是此时的海贼团也只是一个抽象,因为组成海贼团的人已经被抽离了,船员已经和所属的海贼团没有了继承关系。
- 关于海贼世界的船员在船上对应不同的职责担任不同的职务,他们是一个团队,所以可以给船员抽象出一个团队类,用于管理船上的成员。
- 抽象的海贼团只有一个空壳子,所以要赋予其灵魂也就是给它添加船员,此时的海贼团和船员团队可以通过聚合的方式组合成为一个整体。
- 这种解决方案不仅适用于管理海贼团,用于管理海军的各个舰队也是没有问题的。
测试程序:对海贼世界中的 海贼团 和 海军 通过桥接模式进行管理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
| struct Person { Person(string name, string job, string ability, string reward, string beizhu) { this->name = name; this->job = job; this->ability = ability; this->reward = reward; this->beizhu = beizhu; } ~Person() { cout << name << "被析构了..." << endl; } string name; string job; string ability; string reward; string beizhu; };
class AbstractTeam { public: AbstractTeam(string name) : m_name(name) {} string getTeamName() { return m_name; } void addMember(Person* p) { m_teamMap.insert(make_pair(p->name, p)); } void show() { cout << m_name << ": " << endl; for (const auto& item : m_teamMap) { cout << "[name: " << item.second->name << ", job: " << item.second->job << ", abilite: " << item.second->ability << ", reward: " << item.second->reward << ", beizhu: " << item.second->beizhu << "] " << endl; } } virtual ~AbstractTeam() { for (const auto& item : m_teamMap) { delete item.second; } } virtual void executeTask() = 0; protected: string m_name; map<string, Person*> m_teamMap; };
class CaoMaoTeam :public AbstractTeam { public: using AbstractTeam::AbstractTeam; void executeTask() override { cout << "在海上冒险,找到 ONE PIECE 成为海贼王!!! " << endl; } };
class SmokerTeam :public AbstractTeam { public: using AbstractTeam::AbstractTeam; void executeTask() override { cout << "为了正义,先将草帽一网打尽!!! " << endl; } };
class AbstractShip { public: AbstractShip(AbstractTeam* team) :m_team(team) {} void show() { m_team->show(); m_team->executeTask(); } virtual string getName() = 0; virtual void feature() = 0;
protected: AbstractTeam* m_team; };
class Merry :public AbstractShip { public: using AbstractShip::AbstractShip; string getName() override { return "前进 - 梅利号"; } void feature() override { cout << getName() << "-- 船首为羊头,化身船精灵在司法岛舍己救下了草帽一伙!!! " << endl; } };
class HaiJunShip :public AbstractShip { public: using AbstractShip::AbstractShip; string getName() override { return "无敌海军号"; } void feature() override { cout << getName() << "-- 船底由海楼石建造,可以穿过无风带的巨大炮舰!!! " << endl; } };
int main() { CaoMaoTeam* team = new CaoMaoTeam("草帽海贼团"); Person* luffy = new Person("路飞", "船长", "橡胶果实能力者", "30亿贝利", "爱吃肉"); Person* zoro = new Person("索隆", "剑士", "三刀流", "12亿贝利", "路痴"); Person* sanji = new Person("山治", "厨师", "火焰腿", "10亿贝利", "好色"); Person* nami = new Person("娜美", "航海士", "天候棒", "3亿贝利", "喜欢钱"); team->addMember(luffy); team->addMember(zoro); team->addMember(sanji); team->addMember(nami); AbstractShip* ship = new Merry(team); ship->show(); ship->feature(); delete team; delete ship; }
|
8. 组合模式
能将多个对象组成一个树状结构,用以描述部分—整体的层次关系,使得用户对单个对象和组合对象的使用具有一致性,这样的结构性设计模式叫做组合模式
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
| class AbstractTeam { public: AbstractTeam(string name) : m_name(name) {} string getName() { return m_name; } void setParent(AbstractTeam* team) { m_parent = team; } AbstractTeam* getParent() { return m_parent; } virtual bool hasChild() { return false; } virtual void addChild(AbstractTeam* node) {} virtual void removeChild(AbstractTeam* node) {}
virtual void fight() = 0; virtual void display() = 0; virtual ~AbstractTeam() {} protected: string m_name; AbstractTeam* m_parent = nullptr; };
class LeafTeam :public AbstractTeam { public: using AbstractTeam::AbstractTeam; void fight() { cout << m_parent->getName() + m_name + "与黑胡子的船员进行近距离肉搏战... " << endl; } void display() { cout << "我是" << m_parent->getName() << "下属的" << m_name << endl; } ~LeafTeam() { cout << "我是" << m_parent->getName() << "下属的" << m_name << ",战斗已经结束,拜拜... " << endl; } };
class ManagerTeam :public AbstractTeam { public: using AbstractTeam::AbstractTeam; void fight() { cout << m_name + "与黑胡子的恶魔果实能力者战斗... " << endl; } bool hasChild() { return true; } void addChild(AbstractTeam* node) { node->setParent(this); m_children.push_back(node); } void removeChild(AbstractTeam* node) { node->setParent(nullptr); m_children.remove(node); } void display() { string info; for (const auto& item : m_children) { if (item == m_children.back()) { info += item->getName(); } else { info += item->getName() + ", "; } } cout << m_name << "的船队是[" << info << "]" << endl; } list<AbstractTeam*> getChildren() { return m_children; } ~ManagerTeam() { cout << "我是[ " << m_name << " ] 战斗结束,拜拜..." << endl; } private: list<AbstractTeam*> m_children; };
void gameover(AbstractTeam* root) { if (root == nullptr) { return; } if (root && root->hasChild()) { ManagerTeam* team = dynamic_cast<ManagerTeam*>(root); list<AbstractTeam*> children = team->getChildren(); for (const auto& item : children) { gameover(item); } } delete root; }
void fighting() { ManagerTeam* root = new ManagerTeam("草帽海贼团"); vector<string> nameList = { "俊美海贼团","巴托俱乐部","八宝水军","艾迪欧海贼团","咚塔塔海贼团", "巨兵海贼团","约塔玛利亚大船团" }; for (int i = 0; i < nameList.size(); i++) { ManagerTeam* child = new ManagerTeam(nameList.at(i)); root->addChild(child); if (i == nameList.size() - 1) { for (int j = 0; j < 9; j++) { LeafTeam* leaf = new LeafTeam("第" + to_string(j + 1) + "番队"); child->addChild(leaf); leaf->fight(); leaf->display(); } } } } int main() { fighting(); }
|