C++设计模式

风中凌乱的猪头 / 2023-08-24 / 原文

1、创建型模式(隔离变化、封装变化:new的解耦)

1、工厂模式                                                                                                                             

  定义:一个用于创建对象的接口,让子类?(ioc :用户)实例化哪个类,工厂方法使一个类的实例化延迟到子类

  缺点:当产品种类过多,由于每一种产品都需要实现一个工厂类,增加了代码量

  ioc机制:控制翻转(依赖注入:DI)(差点东西,对于ioc的理解)

  因为工厂模式违反了开闭原则,IOC是为了解决这个问题,把一个类的实例化延迟到用户受众,由用户决定什么时候实例化哪个类

 代码

#include <iostream>
#include <string>

using namespace std;
// 水果类
class Fruit
{
public:
    virtual void GetFruit() = 0;
};

class Apple : public Fruit
{
public:
    void GetFruit()
    {
        cout << "我是苹果......."  << endl; 
    }
};

class Pear : public Fruit
{
public:
    void GetFruit()
    {
        cout << "我是梨......."  << endl; 
    }
};

class Banana:public Fruit
{
public:
    void GetFruit()
    {
        cout << "我是香蕉......."  << endl; 
    }
};

class Plum : public Fruit
{
public:
    void GetFruit()
    {
        cout << "我是李子......" << endl;
    }

};


class AbsFactory
{
public:
    virtual Fruit* CreateProduct() = 0;
};

// 苹果工厂
class AppleFactory :public AbsFactory
{
public:
    Fruit* CreateProduct()
    {
        return new Apple;
    }
};

class PearFactory :public AbsFactory
{
public:
    Fruit* CreateProduct()
    {
        return new Pear;
    }
};

class BananaFactory :public AbsFactory
{
public:
    Fruit* CreateProduct()
    {
        return new Banana;
    }
};

class PlumFactory:public AbsFactory
{
public:
    Fruit * CreateProduct()
    {
        return new Plum;
    }
};


template <typename T>
class DynCreatObj
{
public:
    //成员函数模版
    template <typename Obj>
    void registerType(string type)  //将类型保存到map容器中
    {
        function<T *()> func = [](){return new Obj();};

        if(m.find(type) == m.end())
        {
            m.emplace(type,func);
        }
        else
        {
            throw(string("type已存在"));
        }
    }
    
    T * getObj(string type)
    {
        function<T* ()> func;

        if(m.find(type) != m.end())
        {
            func = m[type];

            return func();
        }
        else
        {
             throw(string("type不存在"));
        }
        
    }

private:
    map<string,function<T *()>> m;  //"A" new A(); "B" new B();
};



int main()
{
     string  str;
     
     DynCreatObj<AbsFactory> dny_obj;
     
     dny_obj.registerType<AppleFactory>("apple");
     dny_obj.registerType<BananaFactory>("banana");
     
     cin >> str;
     
     AbsFactory *factory = dny_obj.getObj(str);
     
     Fruit *f = factory->CreateProduct();
     
     f->GetFruit();


    return 0;
}
View Code

2、抽象工厂模式

  定义:为创建一组相关或相互依赖的对象提供一个接口,而且无须指定他们的具体类。

  优点:在有多个业务品种、业务分类时,通过抽象工厂模式生产需要的对象是一个非常好的解决方式

  缺点:加入产品族中要加入一个新的产品,不仅要实现产品类,还有创建相关的工厂接口

 代码

#include<iostream>
using namespace std;

//抽象猫类
class Cat{
public:
    virtual string getType() = 0;
};

//白颜色猫
class WhiteCat:public Cat{
public:
    WhiteCat():Cat(),m_type("WhiteCat"){

    }
    string getType(){
        cout << m_type << endl;
        return m_type;
    }
private:
    string m_type;
};

//黑色猫类
class BlackCat:public Cat{
public:
    BlackCat():Cat(),m_type("BlackCat"){

    }
    string getType(){
        cout << m_type << endl;
        return m_type;
    }
private:
    string m_type;
};

 //抽象狗类
class Dog{
public:
    virtual string getType() = 0;
};

//白色狗类
class WhiteDog:public Dog{
public:
    WhiteDog():Dog(),m_type("WhiteDog"){

    }
    string getType(){
        cout << m_type << endl;
        return m_type;
    }
private:
    string m_type;
};

//黑色狗类
class BlackDog:public Dog{
public:
    BlackDog():Dog(),m_type("BlackDog"){

    }
    string getType(){
        cout << m_type << endl;
        return m_type;
    }
private:
    string m_type;
};

//抽象工厂类
class Pet
 {
 public:
     virtual  Cat* createCat() = 0;
     virtual  Dog* createDog() = 0;
 };

 //白色宠物工厂
class WhitePetFactory
{
public:
     Cat* createCat(){
         return new WhiteCat();
     }
     Dog* creatDog(){
         return new WhiteDog();
     }
};
 //黑色宠物工厂
 class BlackPetFactory
 {
 public:
     Cat* createCat(){
         return new BlackCat();
     }
     Dog* creatDog(){
         return new BlackDog();
     }
 };
View Code

3、单例模式

  定义:确保一个类只有一个实例,而且自行实例化并向整个系统提供这实例(不能让一个程序打开两次:不能同时打开2个迅雷)

  应用:单例模式主要作用是确保一个类只有一个实例存在。单例模式可以用在建立目录、数据库连接等需要单线程操作的场合,用于实现对系统资源的控制

  1、懒汉单例模式

    定义:第一次引用类时,才进行对象实例化

  非线程安全的懒汉单例模式代码

class Singleton
{
public:
    static Singleton* getInstance();
    ~Singleton(){}
​
private:
    Singleton(){}                                        //构造函数私有,防止通过拷贝构造,赋值运算实例化对象
    Singleton(const Singleton& obj) = delete;            //明确拒绝
    Singleton& operator=(const Singleton& obj) = delete; //明确拒绝

    static Singleton* m_pSingleton;
};
​
Singleton* Singleton::m_pSingleton = NULL;
​
Singleton* Singleton::getInstance()
{
    if(m_pSingleton == NULL)
    {
        m_pSingleton = new Singleton;
    }
    return m_pSingleton;
}
View Code

 

  线程安全的懒汉单例模式代码(加了把锁,访问静态变量变成了原子操作)

std::mutex mt;

class Singleton
{
public:
    static Singleton* getInstance();
private:
    Singleton(){}                                    //构造函数私有
    Singleton(const Singleton&) = delete;            //明确拒绝
    Singleton& operator=(const Singleton&) = delete; //明确拒绝

    static Singleton* m_pSingleton;

};
Singleton* Singleton::m_pSingleton = NULL;

Singleton* Singleton::getInstance()
{
    if(m_pSingleton == NULL)
    {
        mt.lock();
        if(m_pSingleton == NULL)
        {
            m_pSingleton = new Singleton();
        }
        mt.unlock();
    }
    return m_pSingleton;
}
View Code

  2、饿汉单例模式

    定义:类加载时,就进行对象实例化

//饿汉式:线程安全,注意一定要在合适的地方去delete它
class Singleton
{
public:
    static Singleton* getInstance();
private:
    Singleton(){}                                    //构造函数私有
    Singleton(const Singleton&) = delete;            //明确拒绝
    Singleton& operator=(const Singleton&) = delete; //明确拒绝
static Singleton* m_pSingleton;
};
​
Singleton* Singleton::m_pSingleton = new Singleton();
​
Singleton* Singleton::getInstance()
{
    return m_pSingleton;
}
View Code

4、建造者模式(定义不太好)

  定义:将一个复杂对象的构建与他的表示分离,是的同样的构建过程可以创建不同的表示

  适用场景:

  • 相同的方法,不同的执行顺序,产生不同的结果时,可以使用建造者模式
  • 多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同时,可以使用该模式
  • 产品类非常复杂,或者产品类中的方法调用顺序不同产生了不同的效能,使用建造者模式

 代码

#include <iostream>
#include <string>

using namespace std;

// 一个产品由零件1 零件2 构成
//具体的产品类
class Product
{
public:
    void setPart1(string part1)
    {
        m_part1 = part1;
    }

    void setPart2(string part2)
    {
        m_part2 = part2;
    }

    string getPart1(){
        cout << m_part1 << endl;
        return m_part1;
    }

    string getPart2(){
        cout << m_part2 << endl;
        return m_part2;
    }

private:
    string m_part1;
    string m_part2;
};

//抽象建造类,提供建造接口。
class OrderBuilder
{
public:
    virtual ~OrderBuilder()
    {
        cout << "~OrderBuilder()" << endl;
    }
    virtual void setOrderPart1() = 0;
    virtual void setOrderPart2() = 0;
    virtual Product* getProduct() = 0;
};

//具体的建造类
class FirstOrderBuilder : public OrderBuilder
{
public:
    FirstOrderBuilder()
    {
        m_Product = new Product;
    }

    ~FirstOrderBuilder()
    {
        cout << "~FirstOrderBuilder()" << endl;
        delete m_Product;
        m_Product = NULL;
    }

    void setOrderPart1()
    {
        m_Product->setPart1("first part1");
    }

    void setOrderPart2()
    {
        m_Product->setPart2("first part2");
    }

    Product* getProduct()
    {
        return m_Product;
    }

private:
    Product* m_Product;
};

//具体的建造类
class SecondOrderBuilder : public OrderBuilder
{
public:
    SecondOrderBuilder()
    {
        m_Product = new Product;
    }

    ~SecondOrderBuilder()
    {
        cout << "~SecondOrderBuilder()" << endl;
        delete m_Product;
        m_Product = NULL;
    }

    void setOrderPart1()
    {
        m_Product->setPart1("second part1");
    }

    void setOrderPart2()
    {
        m_Product->setPart2("second part2");
    }

    Product* getProduct()
    {
        return m_Product;
    }

private:
    Product* m_Product;
};

//Director类,负责管理实例创建的依赖关系,指挥构建者类创建实例
class Director
{
public:
    Director(OrderBuilder* builder) : m_pOrderBuilder(builder)
    {
    }
    void construct()
    {
        m_pOrderBuilder->setOrderPart1();
        m_pOrderBuilder->setOrderPart2();
    }

private:
    OrderBuilder* m_pOrderBuilder;
};


int main()
{
    OrderBuilder* mBuilder = new SecondOrderBuilder;
    Director* director = new Director(mBuilder);
    director->construct();
    Product* order = mBuilder->getProduct();
    order->getPart1();
    order->getPart2();

    delete director;
    director = NULL;

    delete mBuilder;
    mBuilder = NULL;

return 0;
}
View Code

5、原型模式

  定义:允许动态的增加或减少产品类,用原型实例指定创建对象的种类,并且通过这些原型创建新的对象

  特点:

    性能优良,原型模式是在内存二进制流的复制,要比直接new一个对象性能好,特别是在一个循环体内产生大量的对象时,原型模式可以更好地体现其优点。

    逃避构造函数的约束:这既是优点也是缺点,直接在内存中复制,构造函数是不会执行的,因此减少了约束,需要在实际应用时进行权衡考虑。

  使用场景:

    资源优化:类初始化需要消化非常多的资源;

    性能和安全要求的场景:通过new产生一个对象需要非常繁琐的数据准备或者访问权限,可以使用原型模式;

    一个对象多个修改者的场景:一个对象需要提供给其他对象访问,而且各个调用者都需要修改其值时可以考虑使用原型模式复制多个对象供调用者使用。

 代码

#include <iostream>
using namespace std;
//具体的实现类
class Product
{
public:
    Product(int id, string name):m_id(id),m_name(name)
    {
        cout << "Product() id address:" << &m_id << endl;
        cout << "Product() name address:" << &m_name << endl;
    }

    //关键代码拷贝构造函数
    Product(const Product& obj)
    {
        this->m_id = obj.m_id;
        this->m_name = obj.m_name;
        cout << "Product(const Product& obj) id address:" << &m_id << endl;
        cout << "Product(const Product& obj) name address:" << &m_name << endl;
    }
    //关键代码克隆函数,返回return new Sheep(*this)
    Product* clone()
    {
        return new Product(*this);
    }
    void show()
    {
        cout << "id  :" << m_id << endl;
        cout << "name:" << m_name.data() << endl;
    }
private:
    int m_id;
    string m_name;
};
int main()
{
    Product* s1 = new Product(1, "abs");
    s1->show();
    Product* s2 = s1->clone();
    s2->show();

    delete s1;
    s1 = NULL;
    delete s2;
    s2 = NULL;
    return 0;
}
View Code

2、结构型模式(隔离变化,封装变化:类内部结构、对象之间结构的解耦)

1、适配器模式

  定义:将一个类的接口变换成客户端期待的另一种接口(改变接口,统一接口),从而使云本因接口不匹配而无法在一起工作的两个类能在一起工作

  优点:适配器模式可以让两个没有任何关系的类在一起运行;增加了类的透明性;提高了类的复用度;增强代码的灵活性

  场景;修改一个已经投产中的系统时,需要对系统进行扩展,此时使用一个已有的类,但这个类不符合系统中的接口,这时使用适配器模式是最合适的,它可以将不符合系统接口的类进行转换,转换成符合系统接口的、可以使用的类。

 代码

#include<iostream>
using namespace std;
//源角色
class ShuiJiao{
public:
    void makeShuiJiao(){
        cout<<"调制菜料"<<endl;
        cout<<"擀面皮"<<endl;
        cout<<"包饺子"<<endl;
    }
};
//抽象目标类
class HumDun{
public:
    virtual void makeHumDun()=0;
};
//适配类
class FoodAdapter:public HumDun,public ShuiJiao{
public:
    void makeHumDun(){
        makeShuiJiao();
        cout<<"水饺与馄饨步骤一样"<<endl;
    }
};
int main(){
    FoodAdapter foodAdapter;
    foodAdapter.makeShuiJiao();
    foodAdapter.makeHumDun();

}
View Code

2、代理模式(具体类)(这个代码和装饰没有什么区别啊)

  定义:为其他对象提供一种代理以控制对这个对象的访问

  特点:

  ■ 职责清晰:真实的角色实现实际的业务逻辑,不用关心其他非本职的事务,通过后期的代理完成附加的事务,附带的结果就是编程简洁清晰。

  ■ 高扩展性:具体主题角色随需求不同可能有很多种,但只要实现了接口,代理类就完全可以在不做任何修改的情况下代理各种真实主题角色。

  ■ 智能化:代理类可以在运行时才确定需要去代理的真实主题,这是一种强大的功能。

  代码:

#include<iostream>
using namespace std;
//IGamePlayer接口对游戏玩家进行抽象
class IGamePlayer{
public:
    virtual void killBoss() = 0;//杀怪
    virtual void upGrade() = 0;//升级
};
//GamePlayer实现IGamePlayer接口中的方法
class GamePlayer:public IGamePlayer{
public:
    GamePlayer(string name){
        m_name = name;
    }
    void killBoss(){
        cout<<m_name<<"在打怪"<<endl;
    }
    void upGrade(){
        cout<<m_name<<"成功升级"<<endl;
    }
private:
    string m_name;
};
//GamePlayerProxy是代理类
class GamePlayerProxy:public IGamePlayer{
public:
    GamePlayerProxy(IGamePlayer* player){
        this->player = player;
    }
    void killBoss(){
        this->log();
        player->killBoss();
    }
    void upGrade(){
        player->upGrade();
        this->count();
    }
private:
    IGamePlayer* player = NULL;
    void log(){
        cout<<"打怪时间XXX"<<endl;
    }
    void count(){
        cout<<"升一级耗费5小时"<<endl;
    }
};
int main(){
    IGamePlayer* player = new GamePlayer("AA");
    IGamePlayer* prox = new GamePlayerProxy(player);
    prox->killBoss();
    prox->upGrade();
    delete  player;
    player = NULL;
    delete  prox;
    prox = NULL;

}
View Code

3、包装模式

  定义:动态的给一个对象增加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活

  优点:

  ■ 装饰类和被装饰类可以独立发展,而不会相互耦合。即 Component 类无须知道Decorator类,Decorator类是从外部来扩展Component类的功能,而Decorator也不用知道具体的构件。

  ■ 装饰模式是继承关系的一个替代方案。装饰类Decorator,不管装饰多少层,返回的对象还是Component。、

  ■ 装饰模式可以动态地扩展一个实现类的功能。

  缺点:多层的装饰还是比较复杂

  使用场景

  ■ 需要扩展一个类的功能,或给一个类增加附加功能。

  ■ 需要动态地给一个对象增加功能,这些功能可以再动态地撤销。

  ■ 需要为一批类进行改装或加装功能。装饰模式是对继承的有力补充。单纯使用继承时,在一些情况下就会增加很多子类,而且灵活性差,维护也不容易。装饰模式可以替代继承,解决类膨胀的问题

代码:

//包装和代理
一个是组合抽象类
一个是组合具体类

class AbsCal
{
public:
   virtual double get_result(string op) = 0;
};

//已有类:升级功能 --代理
class Cal : public AbsCal
{
public:
    Cal(double a, double b) : m_a(a), m_b(b)
    {

    }

    void setAdd(Operation *add)
    {
        m_add = add;
    }

    void setSub(Operation *sub)
    {
        m_sub = sub;
    }

    double get_result(string op)
    {
        double result;

        if(op == "+")
        {
            result = m_add->get_result(m_a,m_b);
        }
        else if(op == "-")
        {
            result = m_sub->get_result(m_a,m_b);
        }

        return result;
    }

private:
    double m_a;
    double m_b;

    Operation *m_add;
    Operation *m_sub;
};

class File : public AbsCal
{
public:
   File(AbsCal *cal) : m_cal(cal)
   {

   }
   double get_result(string op)
   {
       double result = m_cal->get_result(op);
       saveFile();
       return result;

   }
   void saveFile()
   {
        cout << "Save file" << endl;
   }
private:
   AbsCal *m_cal;
};

class Sqlite3 : public AbsCal
{
public:
   Sqlite3(AbsCal *cal) : m_cal(cal)
   {
    
   }
   double get_result(string op)
   {
       double result = m_cal->get_result(op);
       saveFile();

       return result;

   }
   void saveFile()
   {
        cout << "Save sqlite3" << endl;
   }
private:
   AbsCal *m_cal;
};

class MySql : public AbsCal
{
public:
   MySql(AbsCal *cal) : m_cal(cal)
   {
    
   }
   double get_result(string op)
   {
       double result = m_cal->get_result(op);
       saveFile();
       return result;

   }
   void saveFile()
   {
        cout << "Save Mysql" << endl;
   }
private:
   AbsCal *m_cal;
};

void test()
{
    AbsCal *cal = new Cal(5,6);
    AbsCal *cal2 = new File(cal);
    //抽象
    AbsCal *cal3 = new MySql(cal2);

    cout << cal3->get_result("+") << endl;
}





装饰:和装饰器类
#include <iostream>
#include <sstream>
using namespace std;
//模版
//T类型对象返回string类型
template <class T>
string MyConvertToStr(T obj) {
    stringstream ss;
    ss << obj;
    return ss.str();
}

//基类
class Beverage {
public:
    virtual string getDescription() = 0;
    virtual double cost() = 0;
protected:
    string m_Description;
};

//还是抽象类,加东西抽象
class CondimentDecorate :public Beverage {
public:
    virtual string getDescription() = 0;
protected:
    //构造函数2
    CondimentDecorate(){}
};

//装饰类1:Soy
class Soy :public CondimentDecorate {
public:
    //构造函数
    Soy(Beverage *pBeverage):m_pBeverage(pBeverage){}
    string getDescription() {
        return m_pBeverage->getDescription() + ",加了酱油了";

    }
    double cost() {
        return 0.1 + m_pBeverage->cost();
    }
private:
    //持有被装饰的对象(基类)
    Beverage *m_pBeverage;
};

//装饰类2:Milk
class Milk :public CondimentDecorate {
public:
    Milk(Beverage *pBeverage) :m_pBeverage(pBeverage) {}
    string getDescription() {
        return m_pBeverage->getDescription() + ",加了牛奶了";

    }
    double cost() {
        return 5+ m_pBeverage->cost();
    }
private:
    //持有被装饰的对象
    Beverage *m_pBeverage;
};

class Lattee :public Beverage {
public:
    Lattee() {
        m_Description = "拿铁";
    }
    string getDescription() {
        return m_Description;
    }
    double cost() {
        return 13;
    }
};


class Expresso :public Beverage {
public:
    Expresso() {
        m_Description = "浓缩咖啡";
    }
    string getDescription() {
        return m_Description;
    }
    double cost() {
        return 13;
    }
};

class Mocha :public Beverage {
public:
    Mocha() {
        m_Description = "摩卡";
    }
    string getDescription() {
        return m_Description;
    }
    double cost() {
        return 13;
    }
};

int main(void) {
    Beverage* pBeverage = new Expresso();
    cout << pBeverage->getDescription() << "价格是" << MyConvertToStr(pBeverage->cost()) << endl;
    

    Beverage* pBeverage2 = new Mocha();

    pBeverage2 = new Soy(pBeverage2);
    pBeverage2 = new Soy(pBeverage2);
    cout << pBeverage2->getDescription() << "价格是" << MyConvertToStr(pBeverage2->cost()) << endl;
    system("pause");
    return 0;
}
View Code

4、桥接模式

  定义:将抽象和实现解耦,使得两者可以独立的变化

  优点:

  ■ 抽象和实现分离是桥梁模式的主要特点,是为了解决继承的缺点而提出的设计模式。在该模式下,实现可以不受抽象的约束,不用绑定在一个固定的抽象层次上。

  ■ 实现对客户透明,客户端不用关心细节的实现,它已经由抽象层通过聚合关系完成了封装。

  ■ 提高灵活性和扩展性。

  使用场景

     ■ 一个类存在两个独立变化的维度,且这两个维度都需要进行扩展;

  ■ 对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。

 代码

#include<iostream>
using namespace std;

//抽象颜色类
class Color{
public:
    virtual string getColor() = 0;
};

//抽象形状类
class AbstractShape{
public:
    virtual void draw(Color* color) = 0;
};

//具体形状类
class Circle:public AbstractShape{
    void draw(Color* color){
        cout<<"draw a "+ color->getColor()  +" Circle"<<endl;
    }
};
//具体形状类
class Square:public AbstractShape{
    void draw(Color* color){
        cout<<"draw a "+ color->getColor() +" Square"<<endl;
    }
};
//具体颜色类
class Red:public Color{
     string getColor(){
        return "red";
    }
};
//具体颜色类
class Green:public Color{
     string getColor(){
        return "Green";
    }
};

int main(){
    Color* color = new Green();
    AbstractShape* shape = new Square();
    shape->draw(color);
    delete color;
    color = NULL;
    delete shape;
    shape = NULL;
}
View Code

5、享元模式

  定义:享元模式是对象池的一种实现。类似于线程池,线程池可以避免不停的创建和销毁多个对象,消耗性能。

  作用:缓存共享对象,降低内存消耗

  优点:享元模式的优点在于大幅减少内存中对象的数量,降低程序内存的占用,提高性能。

  缺点:

  ■ 享元模式增加了系统的复杂性,需要分出外部状态和内部状态,而且内部状态具有固化特性,不应该随外部状态改变而改变,这使得程序的逻辑复杂化。

  ■ 享元模式将享元对象的状态外部化,而读取外部状态使得运行时间变长。

  使用场景:

  ■ 系统中有大量的相似对象,这些对象耗费大量的内存。

  ■ 细粒度的对象都具备较接近的外部状态,而且内部状态与环境无关,即对象没有特定身份。

  ■ 需要缓冲池的场景。

代码

#include<iostream>
using namespace std;

//棋子接口Chesspiece是抽象享元,该接口中规范一个落子put()方法,对棋子的坐标进行定位通过参数的形式将外部状态传入
class  Chesspiece{
public:
    virtual void put(int x,int y)=0;
};

//棋子具体享元ChesspieceFlyweight实现棋子接口Chesspiece
class ChesspieceFlyweight:public Chesspiece{
public:
    ChesspieceFlyweight(string color){
        this->color = color;
    }
    void put(int x,int y){
        cout<<color<<"子在("<<x<<","<<y<<")落子"<<endl;
    }
private:
    string color;
};
//棋子工厂ChesspieceFactory是享元工厂,负责创建和管理棋子
class ChesspieceFactory{
public:
    static  Chesspiece* WHITE;
    static  Chesspiece* BLACK;
public:
    static Chesspiece* getChessPiece(string color){
        if(color == ""){
            return WHITE;
        }
        else if(color == ""){
            return BLACK;
        }
        return NULL;
    }

};
Chesspiece* ChesspieceFactory::BLACK = new ChesspieceFlyweight("");
Chesspiece* ChesspieceFactory::WHITE = new ChesspieceFlyweight("");
int main(){
    ChesspieceFactory chesspieceFactory;
    Chesspiece* p1 = chesspieceFactory.getChessPiece("");
    p1->put(1,1);
    Chesspiece* p2 = chesspieceFactory.getChessPiece("");
    p2->put(1,1);
    delete p1;
    p1 = NULL;
    delete p2;
    p2 = NULL;
}
View Code

6、组合模式

  定义:将对象组合成树形结构以表示“部分—整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性

  优点:

  ■ 高层模块调用简单。一棵树形机构中的所有节点都是 Component,局部和整体对调用者来说没有任何区别,即高层模块不必关心自己处理的是单个对象还是整个组合结构,简化了高层模块的代码。

  ■ 节点自由增加。使用组合模式后,如果想增加一个树枝节点、树叶节点只需要找到其父节点即可。

  缺点:

  ■ 不易控制树枝构件的类型;

  ■ 不易使用继承的方法来增加新的行为。

  使用场景:

  ■ 需要描述对象的部分和整体的等级结构,如树形菜单、文件和文件夹管理。

  ■ 需要客户端忽略个体构件和组合构件的区别,平等对待所有的构件。组合模式也是应用广泛的一种设计模式。

 代码:

#include<iostream>
#include <list>
#include <memory>
#include <stdio.h>
#include <string>
using namespace std;

//
class Company {
public:
    virtual string getInfo() = 0;
    virtual  string getName()
    {
        return name;
    }
    virtual string getType() = 0;
protected:
    string name;
    string position;
    int salary;
};
class ConcreteCompany :public Company {
public:
    ConcreteCompany(string name, string position, int salary) {
        this->name = name;
        this->position = position;
        this->salary = salary;
    }
    void add(Company* company) {

        shared_ptr<Company> temp(company);
        companyList.push_back(temp);
    }
    string getType() {
        return "ConcreteCompany";
    }
    void remove(string companyName) {
        list<shared_ptr<Company>>::iterator iter = companyList.begin();
            for (; iter != companyList.end(); iter++)
            {
                    if ((*iter).get()->getName() == companyName)
                    {
                        companyList.erase(iter);
                        return;
                    }
            }
    }
    list<shared_ptr<Company>> getChild() {
        return companyList;
    }
    string getInfo() {
        string info = "";
        info = "名称:" + this->name;
        info = info + "\t职位:" + this->position;
        info = info + "\t薪水:" + to_string(this->salary);
        return info;
    }
private:
    list<shared_ptr<Company>> companyList;
};

class Employee :public Company {
public:
    Employee(string name, string position, int salary) {
        this->name = name;
        this->position = position;
        this->salary = salary;
    }
    string getType() {
        return "Employee";
    }
    string getInfo() {
        string info = "";
        info = "名称:" + this->name;
        info = info + "\t职位:" + this->position;
        info = info + "\t薪水:" + to_string(this->salary);
        return info;
    }
};
void disPlay(ConcreteCompany* root) {

    cout << root->getInfo() << endl;
    list<shared_ptr<Company>> tmp = root->getChild();
    list<shared_ptr<Company>>::iterator iter = tmp.begin();
    for (; iter != tmp.end(); iter++)
    {
        if ((*iter).get()->getType() == string("Employee"))
        {
            cout << (*iter).get()->getInfo() << endl;
        }
        else {
            disPlay((ConcreteCompany*)(*iter).get());
        }
    }

}
int main() {
    ConcreteCompany* root = new ConcreteCompany("张三", "CEO", 100000);
    ConcreteCompany* develop = new ConcreteCompany("李四", "研发组长", 100000);
    ConcreteCompany* sale = new ConcreteCompany("王二", "销售组长", 100000);
    Employee *e1 = new Employee("A", "研发",200);
    Employee *e2 = new Employee("B", "销售", 200);
    Employee *e3 = new Employee("C", "研发", 200);
    Employee *e4 = new Employee("D", "销售", 200);
    root->add(develop);
    root->add(sale);
    develop->add(e1);
    develop->add(e3);
    sale->add(e2);
    sale->add(e4);
    disPlay(root);
    develop->remove("A");
    disPlay(root);
    delete root;
    root = NULL;

}
View Code

 7、外观模式

  定义:要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行。外观模式提供一个高层次的接口,使得子系统更易使用。

  优点:

  ■ 减少系统的相互依赖,所有的依赖都是对Façade对象的依赖,与子系统无关。

  ■ 提高灵活性,不管子系统内部如何变化,只要不影响Facade对象,任何活动都是自由的。

  ■ 提高安全性,Facade中未提供的方法,外界就无法访问,提高系统的安全性。

  注意外观模式最大的缺点是不符合开闭原则,对修改关闭,对扩展开放。

  场景使用:

  ■ 为一个复杂的模块或子系统提供一个供外界访问的接口。

  ■ 子系统相对独立,外界对子系统的访问只要黑箱操作即可。

  ■ 预防风险扩散,使用Façade进行访问操作控制

代码:

#include<iostream>
using namespace std;
class Airport{
public:
    void bookTicket(string from,string to){
        cout<<"订购了从"+ from +"" + to + "的机票"<<endl;
    }
};
class Hotel{
public:
    void reserve(int days){
        cout<<"定了"<<days<<"天的房间"<<endl;
    }
};
class Chauffeur{
public:
    void drive(string to){
        cout<<"司机开车去"+to<<endl;

    }
};
class Secretary{
public:
    void trip(string to,int days){
        airport.bookTicket("上海",to);
        chauffeur.drive("机场");
        hotel.reserve(days);
    }
private:
    Chauffeur chauffeur;
    Hotel hotel;
    Airport airport;
};
int main(){
    Secretary s;
    cout<<"老板告诉秘书出差10天"<<endl;
    s.trip("青岛",10);
}
View Code