2.面对对象设计原则 面对对象设计原则为支持可维护性复用而诞生,这些原则则蕴含在很多设计模式中,他们是从很多设计方案中总结出来的 指导性原则 。
原则的目的 :高内聚、低耦合。
2.1 面向对象设计原则表 名称 定义 单一职责原则 Single Responsibolity Principle 开闭原则 Open-Closed principle, OCP 里氏代换原则 Liskov Substitution Principle, LSP 依赖倒转原则 Dependence Inversion Principle, DIP 接口隔离原则 Interface Segregation Principle, ISP 合成复用原则 Composite Reuse Principle, CRP 迪米特法则 Law of Demeter, LOD
2.2 开闭原则 对扩展开放,对修改关闭。
增加功能是通过增加代码实现的,而不是修改源代码。
🙅错误案例:
以下面 Calculator 类为例,当我需要增加功能:取模运算,我只能修改 getResult()
函数。不符合开闭原则!
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 template <class T >class Calculator {public : Calculator (T a, T b, string operator_string) { this ->m_a = a; this ->m_b = b; this ->m_operator = operator_string; } T getResult () { if (m_operator.compare ("+" ) == 0 ) { return m_a + m_b; } else if (m_operator.compare ("-" ) == 0 ) { return m_a - m_b; } else if (m_operator.compare ("*" ) == 0 ) { return m_a * m_b; } else if (m_operator.compare ("/" ) == 0 ) { return m_a / m_b; } return 0 ; }private : T m_a, m_b; string m_operator; T result; };void test01 () { Calculator<int >* calculator = new Calculator <int >(10 , 20 , "+" ); cout << calculator->getResult () << endl; if (calculator != nullptr ) { delete calculator; calculator = nullptr ; } return ; }
🙆修改为符合开闭原则的案例:
定义一个抽象类 AbstractCalculator
,有两个纯虚函数:setOperatorNumber()
、 getResult()
。
实现加减乘除功能时,只需要继承抽象类 AbstractCalculator
,并重写其虚函数即可。
注意:记得写虚析构函数(原因:delete 父类指针时,只会调用父类的析构函数,无法调用析构子类对象的析构函数)。
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 template <class T >class AbstractCalculator {public : virtual void setOperatorNumber (T a, T b) = 0 ; virtual T getResult () = 0 ; virtual ~AbstractCalculator () {} };template <class T >class PlusCalculator : public AbstractCalculator<T> {public : virtual void setOperatorNumber (T a, T b) { this ->m_a = a; this ->m_b = b; } virtual T getResult () { return m_a + m_b; } virtual ~PlusCalculator () {}private : T m_a, m_b; };template <class T >class SubtractCalculator : public AbstractCalculator<T> {public : virtual void setOperatorNumber (T a, T b) { this ->m_a = a; this ->m_b = b; } virtual T getResult () { return m_a - m_b; } virtual ~SubtractCalculator () {}private : T m_a, m_b; };template <class T >class MultiplyCalculator : public AbstractCalculator<T> {public : virtual void setOperatorNumber (T a, T b) { this ->m_a = a; this ->m_b = b; } virtual T getResult () { return m_a * m_b; } virtual ~MultiplyCalculator () {} private : T m_a, m_b; };template <class T >class DivisionCalculator : public AbstractCalculator<T> {public : virtual void setOperatorNumber (T a, T b) { this ->m_a = a; this ->m_b = b; } virtual T getResult () { return m_a / m_b; } virtual ~DivisionCalculator () {}private : T m_a, m_b; };template <class T >class ModuloCalculator : public AbstractCalculator<T> {public : virtual void setOperatorNumber (T a, T b) { this ->m_a = a; this ->m_b = b; } virtual int getResult () { return m_a % m_b; } virtual ~ModuloCalculator () {}private : T m_a, m_b; };void test01 () { AbstractCalculator<int >* modulo = new ModuloCalculator <int >(); modulo->setOperatorNumber (10 , 20 ); cout << modulo->getResult () << endl; if (modulo != nullptr ) { delete modulo; modulo = nullptr ; } return ; }
2.3 迪米特法则 又叫 最小知识原则 。
知道的越少,建立耦合关系越弱。
**举个例子:**客户的需求是买一个100平的房子,但是并不关心 房子价格、地址、几楼、拥有者。
建立一个中间层,客户不需要和每个房子交流,只需要和中间层(中介)交流就可以。
🙅错误代码实现:
与每个实体类交互,耦合度高!
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 class AbstractHouse {public : virtual int getArea () = 0 ; virtual int getPrice () = 0 ; virtual void Sell () = 0 ; virtual ~AbstractHouse () {} };class HouseA : public AbstractHouse {public : HouseA () { this ->m_area = 100 ; this ->m_price = 1500000 ; } virtual int getArea () { return m_area; } virtual int getPrice () { return m_price; } virtual void Sell () { cout << "售出" << m_area << " 平的房子!" << endl; }private : int m_area; int m_price; };class HouseB : public AbstractHouse {public : HouseB () { this ->m_area = 80 ; this ->m_price = 12000000 ; } virtual int getArea () { return m_area; } virtual int getPrice () { return m_price; } virtual void Sell () { cout << "售出" << m_area << " 平的房子!" << endl; }private : int m_area; int m_price; };class HouseC : public AbstractHouse {public : HouseC () { this ->m_area = 50 ; this ->m_price = 750000 ; } virtual int getArea () { return m_area; } virtual int getPrice () { return m_price; } virtual void Sell () { cout << "售出" << m_area << " 平的房子!" << endl; }private : int m_area; int m_price; };
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 void test01 () { HouseA* house_a = new HouseA (); if (house_a->getArea () == 100 ) { house_a->Sell (); } if (house_a) { delete house_a; house_a = nullptr ; } HouseB* house_b = new HouseB (); if (house_b->getArea () == 100 ) { house_b->Sell (); } if (house_b) { delete house_b; house_b = nullptr ; } HouseC* house_c = new HouseC (); if (house_c->getArea () == 100 ) { house_c->Sell (); } if (house_c) { delete house_c; house_c = nullptr ; } return ; }
🙆符合迪米特法则的代码:
将与每个房子交互的过程交给一个中介类。让用户知道房子的信息越少越好(低耦合)。
为了保持中介类的可扩展性,将中介类定义为抽象类(符合开闭原则)。
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 class AbstractAgency {public : virtual void setHouse () = 0 ; virtual AbstractHouse* SellHouse (int area, int . price = 0 ) = 0 ; virtual ~AbstractAgency () {} };class AgencyArea : public AbstractAgency {public : virtual void setHouse () { AbstractHouse* house_ptr = new HouseA; house_vector.push_back (house_ptr); house_ptr = new HouseB; house_vector.push_back (house_ptr); house_ptr = new HouseC; house_vector.push_back (house_ptr); return ; } virtual AbstractHouse* SellHouse (int area, int price = 0 ) { for (vector<AbstractHouse*>::iterator it = house_vector.begin (); it != house_vector.end (); it++) { if ((*it)->getArea () == area) { (*it)->Sell (); return *it; } } return nullptr ; } ~AgencyArea () { for (vector<AbstractHouse*>::iterator it = house_vector.begin (); it != house_vector.end (); it++) { if (*it) { delete *it; *it = nullptr ; } } }private : vector<AbstractHouse*> house_vector; };void test01 () { AbstractAgency* agency_ptr = new AgencyArea; agency_ptr->setHouse (); if (!agency_ptr->SellHouse (100 )) { cout << "没有买到符合条件的房子!" << endl; } if (agency_ptr) { delete agency_ptr; agency_ptr = nullptr ; } }
如果需求变为:买100平米的房子,价格不过200万。可使用另一个类。
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 class AgencyAreaAndPrice : public AbstractAgency {public : virtual void setHouse () { AbstractHouse* house_ptr = new HouseA; house_vector.push_back (house_ptr); house_ptr = new HouseB; house_vector.push_back (house_ptr); house_ptr = new HouseC; house_vector.push_back (house_ptr); return ; } virtual AbstractHouse* SellHouse (int area, int price = 0 ) { for (vector<AbstractHouse*>::iterator it = house_vector.begin (); it != house_vector.end (); it++) { if ((*it)->getArea () == area && (*it)->getPrice () < price) { (*it)->Sell (); return *it; } } return nullptr ; } ~AgencyAreaAndPrice () { for (vector<AbstractHouse*>::iterator it = house_vector.begin (); it != house_vector.end (); it++) { if (*it) { delete *it; *it = nullptr ; } } }private : vector<AbstractHouse*> house_vector; };void test01 () { AbstractAgency* agency_ptr = new AgencyAreaAndPrice; agency_ptr->setHouse (); if (!agency_ptr->SellHouse (100 , 2000000 )) { cout << "没有买到符合条件的房子!" << endl; } if (agency_ptr) { delete agency_ptr; agency_ptr = nullptr ; } }
2.4 合成复用原则 继承和组合,优先使用组合。
🙅错误的代码:
车类的代码。(正确)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class AbstractCar {public : virtual void Run () = 0 ; };class BMW : public AbstractCar {public : virtual void Run () { cout << "BMW 启动了..." << endl; } virtual ~AbstractCar () {} };class Jeep : public AbstractCar {public : virtual void Run () { cout << "Jeep 启动了..." << endl; } };
Person
继承具体的车,实现开车功能(错误)。
因为人只能开 BMW 这一种车。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Person : public BMW {public : Person (string name) { this ->m_name = name; } void Airing () { cout << this ->m_name >> " 的 " ; Run (); }private : string m_name; };void test01 () { Person* tom = new Person ("Tom" ); tom->Airing (); if (tom) { delete tom; tom = nullptr ; } }
🙆符合合成复用原则的代码:
把抽象车 AbstractCar
作为 Person
的一个参数传入。这就是组合(低耦合性)。
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 class Person {public : Person (string name) { this ->m_name = name; } void Airing (AbstractCar* my_car) { cout << this ->m_name << " 的 " ; my_car->Run (); }private : string m_name; };void test01 () { Person* tom = new Person ("Tom" ); AbstractCar* my_car = new BMW (); tom->Airing (my_car); if (tom) { delete tom; tom = nullptr ; } if (my_car) { delete my_car; my_car = nullptr ; } }
2.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 43 class BankWorker {public : void PayService () { cout << "办理支付业务..." << endl; } void TransferService () { cout << "办理转账业务..." << endl; } void SaveService () { cout << "办理存款业务..." << endl; } };void DoSaveService (BankWorker* worker) { worker->SaveService (); }void DoTransferService (BankWorker* worker) { worker->TransferService (); }void DoPayService (BankWorker* worker) { worker->PayService (); }void test01 () { BankWorker* worker = new BankWorker; DoPayService (worker); DoTransferService (worker); if (worker) { delete worker; worker = nullptr ; } return ; }
🙆符合依赖倒转原则的代码:
底层依赖中层,高层依赖中层。
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 class AbstractWorker {public : virtual void doBusiness () = 0 ; };class SaveBankWorker : public AbstractWorker {public : virtual void doBusiness () { cout << "办理存款业务..." << endl; } };class TransferBankWorker : public AbstractWorker {public : virtual void doBusiness () { cout << "办理转账业务..." << endl; } };class PayBankWorker : public AbstractWorker {public : virtual void doBusiness () { cout << "办理支付业务..." << endl; } };void DoNewBusiness (AbstractWorker* bank_worker) { bank_worker->doBusiness (); return ; }void test01 () { AbstractWorker* bank_worker = new TransferBankWorker; DoNewBusiness (bank_worker); return ; }
3.简单工厂模式 简单工厂模式并不属于 GoF 的 23 种设计模式。
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 class Fruit {public : Fruit (string name) { this ->m_name = name; if (m_name == "apple" ) { m_price = 5 ; } else if (m_name == "banana" ) { m_price = 6 ; } else if (m_name == "pear" ) { m_price = 7 ; } } void getName () { if (m_name == "apple" ) { cout << "我是苹果业务" << endl; } else if (m_name == "banana" ) { cout << "我是香蕉业务" << endl; } else if (m_name == "pear" ) { cout << "我是鸭梨业务" << endl; } }private : string m_name; int m_price; };int main () { Fruit apple ("apple" ) ; Fruit banana ("banana" ) ; Fruit pear = Fruit ("bear" ); apple.getName (); banana.getName (); pear.getName (); }
3.2 角色 工厂角色(Factory):
简单工厂模式的核心。
负责实现创建所有对象的内部逻辑。
外界调用工厂,来创建产品对象。
抽象产品角色(Abstract Product):
具体产品角色(Concrete Product):
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 class AbstractFruit {public : virtual void ShowName () = 0 ; virtual ~AbstractFruit (){} };class Apple : public AbstractFruit {public : Apple () { this ->m_name = "apple" ; } virtual void ShowName () { cout << "我是苹果" << endl; }private : string m_name; };class Banana : public AbstractFruit {public : Banana () { this ->m_name = "banana" ; } virtual void ShowName () { cout << "我是🍌" << endl; }private : string m_name; };class Pear : public AbstractFruit {public : Pear () { this ->m_name = "pear" ; } virtual void ShowName () { cout << "我是鸭梨🍐" << endl; }private : string m_name; };
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 class FruitFactory {public : static AbstractFruit* CreateFruit (string name) { if (name == "apple" ) { return new Apple; } else if (name == "banana" ) { return new Banana; } else if (name == "pear" ) { return new Pear; } } };void test01 () { AbstractFruit* apple = FruitFactory::CreateFruit ("apple" ); apple->ShowName (); delete apple; AbstractFruit* banana = FruitFactory::CreateFruit ("banana" ); banana->ShowName (); delete banana; AbstractFruit* pear = FruitFactory::CreateFruit ("pear" ); pear->ShowName (); delete pear; return ; }
3.4 优缺点 优点:
缺点:
3.5 适用场景 4.工厂方法模式 4.1 为什么需要工厂方法模式 为了解决 简单工厂模式不符合开闭原则 和 单一职责原则 的问题。
4.2 实现 **案例:**利用不同的水果工厂来创建不同的水果。
相比于 简单工厂模式 ,工厂方法模式 将 简单工厂模式 中的工厂类,进行了抽象。
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 class AbstractFruit {public : virtual void ShowName () = 0 ; ~AbstractFruit (){} };class Apple : public AbstractFruit {public : Apple () { this ->m_name = "apple" ; } virtual void ShowName () { cout << "我是苹果" << endl; }private : string m_name; };class Banana : public AbstractFruit {public : Banana () { this ->m_name = "banana" ; } virtual void ShowName () { cout << "我是🍌" << endl; }private : string m_name; };class Pear : public AbstractFruit {public : Pear () { this ->m_name = "pear" ; } virtual void ShowName () { cout << "我是鸭梨🍐" << endl; }private : string m_name; };
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 class AbstractFruitFactory {public : virtual AbstractFruit* CreateFruit () = 0 ; virtual ~AbstractFruitFactory (){} };class AppleFactory : public AbstractFruitFactory {public : virtual AbstractFruit* CreateFruit () { return new Apple; } };class BananaFactory : public AbstractFruitFactory {public : virtual AbstractFruit* CreateFruit () { return new Banana; } };class PearFactory : public AbstractFruitFactory {public : virtual AbstractFruit* CreateFruit () { return new Pear; } };void test01 () { AbstractFruitFactory* factory = new AppleFactory; AbstractFruit* Fruit = factory->CreateFruit (); Fruit->ShowName (); return ; }
4.3 优缺点 缺点:
优点:
4.4 适用场景 5.抽象工厂模式 5.1 为什么需要抽象工厂模式 为了让水果类满足 开闭原则和单一职责原则 ,我们使用简单工厂模式 ;但是工厂类职责太重,工厂类不符合 开闭原则和单一职责原则。
为了使工厂类符合 开闭原则和单一职责原则 ,我们使用 工厂方法模式 ;但是每个工厂只生产一种产品,导致系统中有大量的工厂类,增加系统开销。
为什么解决 工厂方法模式 的问题,我们将相关产品组成一个产品族,由同一个工厂来生产。
PS:当有不同产地的同种水果加入(比如增加 美国苹果、中国苹果),更适合使用抽象工厂。
5.2 产品族和产品等级结构 产品族 :同一产地、同一厂商、功能不同 。
**产品等级:**产地或者厂商不同,功能相同 。
抽象工厂不是针对产品等级结构的,是针对产品族的。
针对产品等级结构,抽象工厂模式不符合开闭原则。(增加产品等级结构,比如增加中国西瓜、美国西瓜、日本西瓜,需要修改中国工厂、美国工厂、日本工厂的类,不符合开闭原则。 ) 针对产品族,抽象工厂符合开闭原则。(增加产品族,比如增加印度苹果、印度香蕉、印度梨,只需要增加印度工厂即可,符合开闭原则。 )
5.3 角色 抽象工厂(Abstract Factory):
具体工厂(Concrete Factory):
实现抽象工厂,创建一个产品族。
创建的每个产品都分别位于一个产品等级结构中。
抽象产品(Abstrcat Product):
具体产品(Concerte Product):
5.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 class AbstractFruit {public : virtual void getName () = 0 ; virtual ~AbstractFruit (){} };class AbstractApple : public AbstractFruit {public : virtual void getName () = 0 ; virtual ~AbstractApple (){} };class ChinaApple : public AbstractApple {public : virtual void getName () { cout << "我是中国苹果!" << endl; } };class AmericaApple : public AbstractApple {public : virtual void getName () { cout << "我是美国苹果!" << endl; } };class JapanApple : public AbstractApple {public : virtual void getName () { cout << "我是日本苹果!" << endl; } };class AbstractBanana : public AbstractFruit {public : virtual void getName () = 0 ; virtual ~AbstractBanana (){} };class ChinaBanana : public AbstractBanana {public : virtual void getName () { cout << "我是中国香蕉!" << endl; } };class AmericaBanana : public AbstractBanana { virtual void getName () { cout << "我是美国香蕉!" << endl; } };class JapanBanana : public AbstractBanana { virtual void getName () { cout << "我是日本香蕉!" << endl; } };class AbstractPear : public AbstractFruit {public : virtual void getName () = 0 ; virtual ~AbstractPear (){} };class ChinaPear : public AbstractPear {public : virtual void getName () { cout << "我是中国梨" << endl; } };class AmericaPear : public AbstractPear {public : virtual void getName () { cout << "我是美国梨" << endl; } };class JapanPear : public AbstractPear {public : virtual void getName () { cout << "我是日本梨" << endl; } };
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 class AbstractFactory {public : virtual AbstractApple* CreateApple () = 0 ; virtual AbstractBanana* CreateBanana () = 0 ; virtual AbstractPear* CreatePear () = 0 ; virtual ~AbstractFactory () {} };class ChinaFactory : public AbstractFactory {public : virtual AbstractApple* CreateApple () { return new ChinaApple; } virtual AbstractBanana* CreateBanana () { return new ChinaBanana; } virtual AbstractPear* CreatePear () { return new ChinaPear; } };class AmericaFactory : public AbstractFactory {public : virtual AbstractApple* CreateApple () { return new AmericaApple; } virtual AbstractBanana* CreateBanana () { return new AmericaBanana; } virtual AbstractPear* CreatePear () { return new AmericaPear; } };class JapanFactory : public AbstractFactory {public : virtual AbstractApple* CreateApple () { return new JapanApple; } virtual AbstractBanana* CreateBanana () { return new JapanBanana; } virtual AbstractPear* CreatePear () { return new JapanPear; } };void test01 () { AbstractFactory* my_factory = new ChinaFactory; AbstractFruit* my_fruit = my_factory->CreateBanana (); my_fruit->getName (); delete my_fruit; delete my_factory; }
5.5 适用场景 6.单例模式 6.1 概念 在现实生活中,有些类的实例化对象的个数只能有一个。
保证一个类,只有一个实例存在,同时提供能对该实例加以访问的全局访问方法。
三个要点:
某个类只能有一个实例;
它必须自行创建这个实例;
它必须自行向整个系统提供这个实例。
6.2 角色 单例:(Singleton)
6.3 实现: 构造函数私有化。
类中增加私有的 静态 指针,初始化为空;在 getInstance 方法中,指向唯一的实例对象。
提供 静态 对外接口 getInstance ,可以让用户获得单例对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Singleton {private : Singleton (){ instance_ptr = new Singleton; }public : static Singleton* getInstance () { return instance_ptr; }private : static Singleton* instance_ptr; }; Singleton* Singleton::instance_ptr = nullptr ;
6.4 懒汉模式 线程不安全。
第一次调用时,才会实例化对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class SingletonLazy {private : SingletonLazy (){}public : static SingletonLazy* getInstance () { if (!instance_ptr) { instance_ptr = new SingletonLazy; } return instance_ptr; }private : static SingletonLazy* instance_ptr; }; SingletonLazy* SingletonLazy::instance_ptr = nullptr ;
6.5 饿汉模式 线程安全。
初始化时,实例化对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class SingletonHungry {private : SingletonHungry (){}public : static SingletonHungry* getInstance () { return instance_ptr; }private : static SingletonHungry* instance_ptr; }; SingletonHungry* SingletonHungry::instance_ptr = new SingletonHungry;
6.6 该不该释放单例对象 不应该给单例对象提供 释放单例对象内存的函数 。
6.7 多线程和单例模式 多个线程并发执行,不一定哪一个先执行完。
PS:测试饿汉模式 “在程序执行前,就实例出单例对象 ”。
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 SingletonHungry {private : SingletonHungry (){ cout << "begin create instance..." << endl; }public : static SingletonHungry* getInstance () { return instance_ptr; }private : static SingletonHungry* instance_ptr; }; SingletonHungry* SingletonHungry::instance_ptr = new SingletonHungry;int main () { cout << "main() begin..." << endl; SingletonHungry::getInstance (); return 0 ; }
6.8 适用场景 7.代理模式Proxy 7.1 概念 构造型的设计模式之一。
代理模式可以 为其他对象提供一种代理 ,以 控制对该对象的访问 。
所谓代理,就是与代理元(被代理的对象)具有相同的接口的类,客户端必须通过代理与代理元交互。
7.2 角色 抽象主题(Subject):
真实主题(RealSubject):
代理主题(Proxy):
7.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 class AbstractInterface {public : virtual void Run () = 0 ; virtual ~AbstractInterface (){} };class MySystem : public AbstractInterface {public : virtual void Run () { cout << "Begin MySystem..." << endl; } };class MySystemProxy : public AbstractInterface {public : MySystemProxy (string user_name, string user_password) { this ->m_user_name = user_name; this ->m_user_passworld = user_password; my_system_ptr = new MySystem; } virtual void Run () { if (CheckUser ()) { cout << "用户名和密码正确,验证通过!" << endl; this ->my_system_ptr->Run (); } else { cout << "用户名和密码错误,权限不足!" << endl; } } ~MySystemProxy (){ if (my_system_ptr) { delete my_system_ptr; my_system_ptr = nullptr ; } }private :bool CheckUser () { if (m_user_passworld == "admin" && m_user_name == "admin" ) { return true ; } return false ; }private : string m_user_name; string m_user_passworld; MySystem* my_system_ptr; };int client () { string user_name = "admin" , user_passworld = "admin" ; AbstractInterface* begin = new MySystemProxy (user_name, user_passworld); begin->Run (); if (begin) { delete begin; begin = nullptr ; } return 0 ; }
7.4 优缺点 优点:
缺点:
7.5 适用场景 为其他对象提供一种代理,以 控制对该对象的访问 。
8.外观模式Facada 8.1 概念 根据迪米特法则,如果两个类不必直接通信,那么两个类就不应该发生直接的相互作用。
Facada模式为一组具有类似功能的类群,比如类库,子系统等等,提供一个一致的简单的界面(该界面就叫做 Facade)。
8.2 角色 外观角色(Facade):
子系统角色(SubSystem):
8.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 class System1 {public : void Run () { cout << "System1 启动..." << endl; } };class System2 {public : void Run () { cout << "System2 启动..." << endl; } };class System3 {public : void Run () { cout << "System3 启动..." << endl; } };class System4 {public : void Run () { cout << "System4 启动..." << endl; } };
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 class Facade {public : Facade () { System1_ptr = new System1; System2_ptr = new System2; System3_ptr = new System3; System4_ptr = new System4; } void Run () { System1_ptr->Run (); System2_ptr->Run (); System3_ptr->Run (); System4_ptr->Run (); } ~Facade () { if (System1_ptr) { delete System1_ptr; System1_ptr = nullptr ; } if (System2_ptr) { delete System1_ptr; System2_ptr = nullptr ; } if (System3_ptr) { delete System1_ptr; System3_ptr = nullptr ; } if (System4_ptr) { delete System1_ptr; System4_ptr = nullptr ; } }private : System1* System1_ptr; System2* System2_ptr; System3* System3_ptr; System4* System4_ptr; };void Client () { Facade facade; facade.Run (); return ; }
8.4 家庭影院案例 实现KTV模式:电视打开,灯关掉,音响打开,麦克风打开,DVD打开;
实现游戏模式:电视打开,音响打开,游戏机打开。
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 class TV {public : void On () { cout << "电视机打开..." << endl; } void Off () { cout << "电视机关闭..." << endl; } };class Light {public : void On () { cout << "灯打开..." << endl; } void Off () { cout << "灯关闭..." << endl; } };class Audio {public : void On () { cout << "音响打开..." << endl; } void Off () { cout << "音响关闭..." << endl; } };class Mircophone {public : void On () { cout << "麦克风打开..." << endl; } void Off () { cout << "麦克风关闭..." << endl; } };class Game {public : void On () { cout << "游戏机打开..." << endl; } void Off () { cout << "游戏机关闭..." << endl; } };class DVDPlayer {public : void On () { cout << "DVD打开..." << endl; } void Off () { cout << "DVD关闭..." << endl; } };
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 class FacadeKTV {public : FacadeKTV () { tv = new TV; light = new Light; audio = new Audio; mircophone = new Mircophone; DVD_player = new DVDPlayer; game = new Game; } void On () { tv->On (); light->Off (); audio->On (); mircophone->On (); DVD_player->On (); game->Off (); } void Off () { tv->Off (); light->On (); audio->Off (); mircophone->Off (); DVD_player->Off (); game->Off (); } ~FacadeKTV () { if (tv) { delete tv; tv = nullptr ; } if (light) { delete light; light = nullptr ; } if (audio) { delete audio; audio = nullptr ; } if (mircophone) { delete mircophone; mircophone = nullptr ; } if (DVD_player) { delete DVD_player; DVD_player = nullptr ; } if (game) {; delete game; game = nullptr ; } } private : TV* tv; Light* light; Audio* audio; Mircophone* mircophone; DVDPlayer* DVD_player; Game* game; };
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 class FacadeGame {public : FacadeGame () { tv = new TV; light = new Light; audio = new Audio; mircophone = new Mircophone; DVD_player = new DVDPlayer; game = new Game; } void On () { tv->On (); light->Off (); audio->On (); mircophone->Off (); DVD_player->Off (); game->On (); } void Off () { tv->Off (); light->On (); audio->Off (); mircophone->Off (); DVD_player->Off (); game->Off (); } ~FacadeGame () { if (tv) { delete tv; tv = nullptr ; } if (light) { delete light; light = nullptr ; } if (audio) { delete audio; audio = nullptr ; } if (mircophone) { delete mircophone; mircophone = nullptr ; } if (DVD_player) { delete DVD_player; DVD_player = nullptr ; } if (game) {; delete game; game = nullptr ; } } private : TV* tv; Light* light; Audio* audio; Mircophone* mircophone; DVDPlayer* DVD_player; Game* game; };void Client () { FacadeGame* facade = new FacadeGame; facade->On (); }
8.4 优缺点 优点:
缺点:
8.5 适用场景 9.适配器模式 9.1 概念 将已经写好的接口(但是这个接口不符合需求),转化为目标需要的接口。
9.2 角色 目标抽象类(Target):
适配器类(Apadter):
9.3 实现 **案例:**Client 调用带有一个参数的函数,但是现在只有带有两个参数的函数对象,通过适配器,使带有两个参数的函数对象,成功被 Client 调用。
Adaptee 等待着被适配(两个参数)。
Client 只能使用一个参数的函数。
Adapter 将 Adaptee 适配为 Client 可以使用的函数。
将 Adaptee 作为自己的私有成员。 重写父类 Target 的方法。并在方法中,调用 Adaptee 函数。 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 struct Print { void operator () (int v, int parameter) { cout << v + parameter << endl; } };class Target {public : virtual void operator () (int v) = 0 ; };class Adapter : public Target {public : Adapter (int parameter) { this ->parameter = parameter; } virtual void operator () (int v) { print (v, parameter); }private : int parameter; Print print; };int main () { vector<int > v; for (int i = 0 ; i < 10 ; i++) { v.push_back (i); } for_each(v.begin (), v.end (), Adapter (10 )); }
9.4 手机充电器案例 **案例:**利用适配器,用 220V 电压给 5V 的手机充电。
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 class Adaptee {public : void Use220V () { cout << "使用 220V 充电..." << endl; } };class Target {public : virtual void Use5V () = 0 ; virtual ~Target () {} };class Adapter : public Target {public : virtual void Use5V () { cout << "对电压进行适配..." << endl; v220.Use220V (); }private : Adaptee v220; };class Phone {public : Phone () { V5 = new Adapter; } void Charge () { cout << "手机进行充电..." << endl; V5->Use5V (); } ~Phone () { if (V5) { delete V5; } }private : Target* V5; };
10.模版方法模式 10.1 概念 定义一个算法框架,子类继承并重写其中某一个或者多个算法。
10.2 角色 抽象类(AbstractClass):
具体子类(concreteClass):
10.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 class DrinkTemplate {public : virtual void BoilWater () = 0 ; virtual void Brew () = 0 ; virtual void PourInCup () = 0 ; virtual void AddCondiments () = 0 ; virtual bool CustomWantsCondiments () { return true ; } void Make () { BoilWater (); Brew (); PourInCup (); if (CustomWantsCondiments ()) { AddCondiments (); } } };class Coffee : public DrinkTemplate {public : virtual void BoilWater () { cout << "煮农夫山泉..." << endl; } virtual void Brew () { cout << "冲泡咖啡..." << endl; } virtual void PourInCup () { cout << "咖啡倒入杯中..." << endl; } virtual void AddCondiments () { cout << "加牛奶..." << endl; } virtual bool CustomWantsCondiments () { return true ; } };class Tea : public DrinkTemplate {public : virtual void BoilWater () { cout << "煮农夫山泉..." << endl; } virtual void Brew () { cout << "冲泡茶叶..." << endl; } virtual void PourInCup () { cout << "茶水倒入杯中..." << endl; } virtual bool CustomWantsCondiments () { return false ; } };void Client () { DrinkTemplate* drink = new Coffee; drink->Make (); return ; }
10.4 优缺点: 优点:
抽象类中形式化的定义一个算法,让子类来处理细节,子类中并不会改变算法的执行顺序。
可以实现一种反向控制,通过重写钩子函数,来控制某些步骤是否执行。
更换算法中某一步骤很容易,符合开闭原则和单一职责原则。
缺点:
11策略模式 11.1 概念 定义一系列算法,并将每个算法封装起来,使他们还可以互相替换。
策略模式,让算法独立于使用它的客户端。
11.2 角色 环境类(Context):
抽象策略类(Strategy):
具体策略类(ConcreteStrategy):
11.3 实现 **案例:**人物使用不同的装备进行战斗。
匕首 和 AK47 继承抽象武器类,并实现其抽象方法。
人(Charater)类中,有一个抽象策略类的指针。用来调用不同的具体策略。
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 class WeaponStrategy {public : virtual void Use () = 0 ; virtual ~WeaponStrategy () {} };class AK47 : public WeaponStrategy {public : virtual void Use () { cout << "使用 AK47 ..." << endl; } };class Knife : public WeaponStrategy {public : virtual void Use () { cout << "使用匕首..." << endl; } };class Character {public : void setWeapon (WeaponStrategy* weapon) { this ->m_weapon = weapon; } void UseWeapon () { m_weapon->Use (); }private : WeaponStrategy* m_weapon; };void Client () { Character character; WeaponStrategy* weapon = new AK47; character.setWeapon (weapon); character.UseWeapon (); delete weapon; return ; }
11.4 优缺点 优点:
缺点:
12.命令模式 别名:动作(Action)模式、事务(Transaction)模式。
12.1 概念 命令模式的本质是对请求进行封装,一个请求对应于一个命令(命令类),将发出命令的责任(客户端)和执行命令的责任(服务端)分割开。
12.2 角色 抽象命令类(Command):
具体命令类(Concrete Command):
调用者(Invoker):
接收者(Receiver):
12.3 实现 案例: 客户端产生了 增加金币、增加钻石、给玩家穿装备、给玩家升级 的请求,因为有很多请求,服务器接收到这些请求,先将这些请求存入队列,然后挨个处理请求。
接受者先定义好协议类。
将协议封装成命令类,继承抽象命令类。
调用者利用抽象命令类的指针,调用,被封装的类(Receiver)。
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 class HandleClientProtocol {public : void AddMoney () { cout << "给玩家增加金币." << endl; } void AddDiamond () { cout << "给玩家增加钻石." << endl; } void AddEquipment () { cout << "给玩家穿装备." << endl; } void AddLevel () { cout << "给玩家升级." << endl; } };class AbstractCommand {public : virtual void Handle () = 0 ; };class AddMoneyCommand : public AbstractCommand {public : AddMoneyCommand (HandleClientProtocol* protocol) { this ->m_protocol = protocol; } virtual void Handle () { m_protocol->AddMoney (); }public : HandleClientProtocol* m_protocol; };class AddDiamondCommand : public AbstractCommand {public : AddDiamondCommand (HandleClientProtocol* protocol) { this ->m_protocol = protocol; } virtual void Handle () { m_protocol->AddDiamond (); }public : HandleClientProtocol* m_protocol; };class AddEquipmentCommand : public AbstractCommand {public : AddEquipmentCommand (HandleClientProtocol* protocol) { this ->m_protocol = protocol; } virtual void Handle () { m_protocol->AddEquipment (); }public : HandleClientProtocol* m_protocol; };class AddLevelCommand : public AbstractCommand {public : AddLevelCommand (HandleClientProtocol* protocol) { this ->m_protocol = protocol; } virtual void Handle () { m_protocol->AddLevel (); }public : HandleClientProtocol* m_protocol; };class Server {public : void AddRequest (AbstractCommand* command) { m_commands_queue.push (command); } void StartHandle () { while (!m_commands_queue.empty ()) { AbstractCommand* command = m_commands_queue.front (); command->Handle (); m_commands_queue.pop (); } }public : queue<AbstractCommand*> m_commands_queue; };void Test01 () { HandleClientProtocol* protocol = new HandleClientProtocol; AbstractCommand* add_money = new AddMoneyCommand (protocol); AbstractCommand* add_diamond = new AddDiamondCommand (protocol); AbstractCommand* add_equipment = new AddEquipmentCommand (protocol); AbstractCommand* add_level = new AddLevelCommand (protocol); Server* server = new Server; server->AddRequest (add_money); server->AddRequest (add_diamond); server->AddRequest (add_equipment); server->AddRequest (add_level); server->StartHandle (); return ; }
12.4 优缺点 优点:
缺点:
13.观察者模式 13.1 概念 观察者 观察 被观察目标 ,如果 被观察目标 的状态发生改变,观察者 做出相应的改变。
13.2 角色
被观察者或目标,抽象主题(Subject):
具体被观察者或目标,具体主题(ConcreteSubject):
观察者(Observer):
具体观察者(ConcreteObserver):
13.3 实现 **案例:**当 boss 存活时,英雄攻击 boss,当 boss 死去,英雄停止攻击。
boss 是观察对象,hero 是观察者。
boss 和 hero 都要抽象出来。
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 AbstractHero {public : virtual void Updata () = 0 ; };class HeroA : public AbstractHero {public : HeroA () { cout << "英雄A正在攻击BOSS..." << endl; } virtual void Updata () { cout << "英雄A停止攻击BOSS,待机状态..." << endl; } };class HeroB : public AbstractHero {public : HeroB () { cout << "英雄B正在攻击BOSS..." << endl; } virtual void Updata () { cout << "英雄B停止攻击BOSS,待机状态..." << endl; } };class HeroC : public AbstractHero {public : HeroC () { cout << "英雄C正在攻击BOSS..." << endl; } virtual void Updata () { cout << "英雄C停止攻击BOSS,待机状态..." << endl; } };class AbstractBoss {public : virtual void AddHero (AbstractHero* hero) = 0 ; virtual void DeleteHero (AbstractHero* hero) = 0 ; virtual void notify () = 0 ; };class BossA : public AbstractBoss {public : virtual void AddHero (AbstractHero* hero) { hero_ptr_list.push_back (hero); } virtual void DeleteHero (AbstractHero* hero) { hero_ptr_list.remove (hero); } virtual void notify () { for (list<AbstractHero*>::iterator it = hero_ptr_list.begin (); it != hero_ptr_list.end (); it++) { (*it)->Updata (); } }public : list<AbstractHero*> hero_ptr_list; };void Test01 () { AbstractHero* heroA = new HeroA; AbstractHero* heroB = new HeroB; AbstractHero* heroC = new HeroC; AbstractBoss* boss_A = new BossA; boss_A->AddHero (heroA); boss_A->AddHero (heroB); boss_A->AddHero (heroC); cout << "______________heroC阵亡..." << endl; boss_A->DeleteHero (heroC); cout << "______________boss_A死了,通知其他英雄..." << endl; boss_A->notify (); return ; }
13.4 优缺点 优点:
缺点:
如果一个观察目标有多个直接或者间接的观察者,将所有观察者都通知到会花费很多时间。
如果观察者和观察目标之间存在循环依赖,观察目标会触发他们之间进行循环调用,可能导致系统崩溃。
观察者模式没有相应的机制让观察者知道所观察的目标对象怎么发生变化的,而仅仅是只知道发生了变化。
14.装饰模式Decorator 又叫包装模式。
14.1 概念 14.2 角色 抽象构件(Component):
具体构件(ConcreteComponent):
抽象装饰类(Decorator):
具体装饰类(ConcreteDecorator):
14.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 class AbstractHero {public : virtual void ShowStatus () = 0 ; virtual ~AbstractHero (){}public : int m_hp; int m_mp; int m_ap; int m_df; };class HeroA : public AbstractHero {public : HeroA () { m_hp = 0 ; m_mp = 0 ; m_ap = 0 ; m_df = 0 ; } virtual void ShowStatus () { cout << "血量:" << m_hp << endl; cout << "魔法:" << m_mp << endl; cout << "攻击:" << m_ap << endl; cout << "防御:" << m_df << endl; } };class AbstractEquipment : public AbstractHero {public : AbstractEquipment (AbstractHero* hero) { this ->m_hero = hero; } virtual void ShowStatus () = 0 ;public : AbstractHero* m_hero; };class KuangtuEquipment : public AbstractEquipment {public : KuangtuEquipment (AbstractHero* hero) : AbstractEquipment (hero) {} void AddKuangtu () { cout << "英雄穿上狂徒之后,防御力加30..." << endl; this ->m_hp = this ->m_hero->m_hp; this ->m_mp = this ->m_hero->m_mp; this ->m_ap = this ->m_hero->m_ap; this ->m_df = this ->m_hero->m_df + 30 ; delete m_hero; } virtual void ShowStatus () { AddKuangtu (); cout << "血量:" << m_hp << endl; cout << "魔法:" << m_mp << endl; cout << "攻击:" << m_ap << endl; cout << "防御:" << m_df << endl; }public : int m_hp; int m_mp; int m_ap; int m_df; };class WujinEquipment : public AbstractEquipment {public : WujinEquipment (AbstractHero* hero) : AbstractEquipment (hero) {} void AddWujin () { cout << "英雄穿上无尽之刃之后,攻击力加100..." << endl; this ->m_hp = this ->m_hero->m_hp; this ->m_mp = this ->m_hero->m_mp; this ->m_ap = this ->m_hero->m_ap + 100 ; this ->m_df = this ->m_hero->m_df; delete m_hero; } virtual void ShowStatus () { AddWujin (); cout << "血量:" << m_hp << endl; cout << "魔法:" << m_mp << endl; cout << "攻击:" << m_ap << endl; cout << "防御:" << m_df << endl; }public : int m_hp; int m_mp; int m_ap; int m_df; };void Test01 () { AbstractHero* hero = new HeroA; hero->ShowStatus (); cout << "---------------给英雄穿上衣服..." << endl; hero = new KuangtuEquipment (hero); hero->ShowStatus (); return ; }