C++设计模式-工厂

简单工厂模式

        

优点:

  1. 工厂类包含必要的逻辑判断,可以决定在什么时候创建哪一个产品的实例。客户端可以免除直接创建产品对象的职责,很方便的创建出相应的产品。工厂和产品的职责区分明确。
  2. 客户端无需知道所创建具体产品的类名,只需知道参数即可。
  3. 也可以引入配置文件,在不修改客户端代码的情况下更换和添加新的具体产品类。

缺点:

  1. 简单工厂模式的工厂类单一,负责所有产品的创建,职责过重,一旦异常,整个系统将受影响。且工厂类代码会非常臃肿,违背高聚合原则。
  2. 使用简单工厂模式会增加系统中类的个数(引入新的工厂类),增加系统的复杂度和理解难度
  3. 系统扩展困难,一旦增加新产品不得不修改工厂逻辑,在产品类型较多时,可能造成逻辑过于复杂
  4. 简单工厂模式使用了 static 工厂方法,造成工厂角色无法形成基于继承的等级结构。

应用场景

对于产品种类相对较少的情况,考虑使用简单工厂模式。使用简单工厂模式的客户端只需要传入工厂类的参数,不需要关心如何创建对象的逻辑,可以很方便地创建所需产品。

示例图:

C++设计模式-工厂_第1张图片

 简单工厂案例:

C++设计模式-工厂_第2张图片

#include 
using namespace std;

//简单工厂案例

class AbstractFruit {
public:
    virtual void ShowName() = 0;
};

//苹果
class Apple : public AbstractFruit {
public:
    virtual void ShowName() {
        cout << "我是苹果" << endl;
    }
};

//香蕉
class Banana : public AbstractFruit {
public:
    virtual void ShowName() {
        cout << "我是香蕉" << endl;
    }
};

//鸭梨
class Pear : public AbstractFruit {
public:
    virtual void ShowName() {
        cout << "我是鸭梨" << endl;
    }
};

//水果工厂
class FruitFactory {
public:
    //设置为静态 为该类的所有对象共享
    static AbstractFruit* CreateFruit(string flag) {
        if (flag == "apple") {
            return new Apple;
        }
        else if (flag == "banana") {
            return new Banana;
        }
        else if (flag == "pear") {
            return new Pear;
        }
        else {
            return NULL;
        }
    }
};

void test01() {
    //创建一个工厂对象
    FruitFactory* factory = new FruitFactory;

    //这里我们发现不再像普通的多态一样需要new Apple;
    //而是在工厂的成员函数参数中传入一个string
    //让工厂类自动帮我们创建一个Apple对象 
    //不用考虑创建过程 拿来直接用 减少了耦合性
    AbstractFruit* fruit = factory->CreateFruit("apple");
    fruit->ShowName();
    delete fruit;

    fruit = factory->CreateFruit("banana");
    fruit->ShowName();
    delete fruit;

    fruit = factory->CreateFruit("pear");
    fruit->ShowName();
    delete fruit;

    delete factory;


}   
int main() {
    test01();
    return 0;
}

总结:好代码就是让耦合性不断的变低 这里直接传一个string就可以创建对象了 比传统的多态更进了一步 

工厂方法模式 

优点:

  • 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程。
  • 灵活性增强,对于新产品的创建,只需多写一个相应的工厂类。
  • 典型的解耦框架。高层模块只需要知道产品的抽象类,无须关心其他实现类,满足迪米特法则、依赖倒置原则和里氏替换原则。

缺点:

  • 类的个数容易过多,增加复杂度
  • 增加了系统的抽象性和理解难度
  • 抽象产品只能生产一种产品,此弊端可使用抽象工厂模式解决。

应用场景:

  • 客户只知道创建产品的工厂名,而不知道具体的产品名。如 TCL 电视工厂、海信电视工厂等。
  • 创建对象的任务由多个具体子工厂中的某一个完成,而抽象工厂只提供创建产品的接口。
  • 客户不关心创建产品的细节,只关心产品的品牌

思考:简单工厂模式虽然降低了耦合性 但是不符合开闭原则 增加一个水果类需要修改工厂类的源代码 如何让工厂也符合开闭原则呢? 答案就是让工厂也抽象出去

示例图:

C++设计模式-工厂_第3张图片

简单工厂模式 + 开闭原则 = 工厂方法模式 

 C++设计模式-工厂_第4张图片

#include 
using namespace std;

//工厂方法案例

class AbstractFruit {
public:
    virtual void ShowName() = 0;
};


//苹果
class Apple : public AbstractFruit {
public:
    virtual void ShowName() {
        cout << "我是苹果" << endl;
    }
};

//香蕉
class Banana : public AbstractFruit {
public:
    virtual void ShowName() {
        cout << "我是香蕉" << endl;
    }
};

//鸭梨
class Pear : public AbstractFruit {
public:
    virtual void ShowName() {
        cout << "我是鸭梨" << endl;
    }
};

//抽象工厂
class AbstractFruitFactory {
public:
    virtual AbstractFruit* CreateFruit() = 0;
};

//苹果工厂
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 = NULL;
    AbstractFruit* fruit = NULL;

    //创建一个苹果工厂对象 用抽象类factory接收
    factory = new AppleFactory;
    //用factory接口去访问子类CreateFruit成员函数
    //在CreateFruit()内部返回了一个水果Apple类对象
    //并用水果的抽象父类接收
    fruit = factory->CreateFruit();
    //使用水果的抽象类接口去访问水果子类的成员函数ShowName()
    fruit->ShowName();

    delete fruit;
    delete factory;

    //创建一个香蕉工厂
    factory = new BananaFactory;
    fruit = factory->CreateFruit();
    fruit->ShowName();

    delete fruit;
    delete factory;

    //创建一个鸭梨工厂
    factory = new PearFactory;
    fruit = factory->CreateFruit();
    fruit->ShowName();

    delete fruit;
    delete factory;
}   

int main() {
    test01();
    return 0;
}

 总结:可以看出来代码量成倍的增长 增加了抽象理解难度 在工厂方法模式下 当我们想要增加一种新的水果 我们只需要增加一个水果类和一个对应的水果工厂类即可 不需要修改源代码

所以说如果后期不需要新增太多的类 可以用简单工厂模式 而如果后期需要不断的新增类 那么工厂方法模式更易于维护

 抽象工厂模式

        抽象工厂(AbstractFactory)模式的定义:是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。

抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品。

使用抽象工厂模式一般要满足以下条件。

  • 系统中有多个产品族,每个具体工厂创建同一族但属于不同等级结构的产品。
  • 系统一次只可能消费其中某一族产品,即同族的产品一起使用。


抽象工厂模式除了具有工厂方法模式的优点外,其他主要优点如下。

  • 可以在类的内部对产品族中相关联的多等级产品共同管理,而不必专门引入多个新的类来进行管理。
  • 当需要产品族时,抽象工厂可以保证客户端始终只使用同一个产品的产品组。
  • 抽象工厂增强了程序的可扩展性,当增加一个新的产品族时,不需要修改原代码,满足开闭原则。


其缺点是:当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。增加了系统的抽象性和理解难度。

示例图:

C++设计模式-工厂_第5张图片

 C++设计模式-工厂_第6张图片

#include 
using namespace std;

//抽象工厂案例

//首先我们根据产品族抽象出来三种水果
//抽象苹果
class AbstractApple {
public:
    virtual void ShowName() = 0;
};

//中国苹果
class ChinaApple : public AbstractApple {
public:
    virtual void ShowName() {
        cout << "中国苹果" << endl;
    }
};

//美国苹果
class USAApple : public AbstractApple {
public:
    virtual void ShowName() {
        cout << "美国苹果" << endl;
    }
};

//巴西苹果
class BrasiliaApple : public AbstractApple {
public:
    virtual void ShowName() {
        cout << "巴西苹果" << endl;
    }
};

//抽象香蕉------------------------------------
class AbstractBanana {
public:
    virtual void ShowName() = 0;
};

//中国香蕉
class ChinaBanana : public AbstractBanana {
public:
    virtual void ShowName() {
        cout << "中国香蕉" << endl;
    }
};

//美国香蕉
class USABanana : public AbstractBanana {
public:
    virtual void ShowName() {
        cout << "美国香蕉" << endl;
    }
};

//巴西香蕉
class BrasiliaBanana : public AbstractBanana {
public:
    virtual void ShowName() {
        cout << "巴西香蕉" << endl;
    }
};

//抽象鸭梨-------------------------------
class AbstractPear {
public:
    virtual void ShowName() = 0;
};

//中国鸭梨
class ChinaPear : public AbstractPear {
public:
    virtual void ShowName() {
        cout << "中国鸭梨" << endl;
    }
};

//美国鸭梨
class USAPear : public AbstractPear {
public:
    virtual void ShowName() {
        cout << "美国鸭梨" << endl;
    }
};

//巴西鸭梨
class BrasiliaPear : public AbstractPear {
public:
    virtual void ShowName() {
        cout << "巴西鸭梨" << endl;
    }
};

//抽象工厂 针对产品族的--------------------------
class AbstractFactory {
public:
    virtual AbstractApple* CreateApple() = 0;
    virtual AbstractBanana* CreateBanana() = 0;
    virtual AbstractPear* CreatePear() = 0;
};

//中国工厂
class ChinaFactory : public AbstractFactory {
public:
    virtual AbstractApple* CreateApple() {
        return new ChinaApple;
    }
    virtual AbstractBanana* CreateBanana() {
        return new ChinaBanana;
    }
    virtual AbstractPear* CreatePear() {
        return new ChinaPear;
    }
};

//美国工厂
class USAFactory : public AbstractFactory {
public:
    virtual AbstractApple* CreateApple() {
        return new USAApple;
    }
    virtual AbstractBanana* CreateBanana() {
        return new USABanana;
    }
    virtual AbstractPear* CreatePear() {
        return new USAPear;
    }
};

//巴西工厂
class BrasiliaFactory : public AbstractFactory {
public:
    virtual AbstractApple* CreateApple() {
        return new BrasiliaApple;
    }
    virtual AbstractBanana* CreateBanana() {
        return new BrasiliaBanana;
    }
    virtual AbstractPear* CreatePear() {
        return new BrasiliaPear;
    }
};

void test01() {
    AbstractFactory* factory = NULL;
    AbstractApple* apple = NULL;
    AbstractBanana* banana = NULL;
    AbstractPear* pear = NULL;

    //中国工厂
    //创建一个中国工厂对象 用factory抽象类接收
    factory = new ChinaFactory;
    //抽象父类访问子类的成员函数 返回一个中国苹果类 
    //用抽象苹果去接收
    apple = factory->CreateApple();
    banana = factory->CreateBanana();
    pear = factory->CreatePear();

    //父类抽象苹果访问子类中国苹果的成员函数ShowName()
    apple->ShowName();
    banana->ShowName();
    pear->ShowName();

    delete pear;
    delete banana;
    delete apple;
    delete factory;

    //美国工厂
    factory = new USAFactory;
    apple = factory->CreateApple();
    banana = factory->CreateBanana();
    pear = factory->CreatePear();

    apple->ShowName();
    banana->ShowName();
    pear->ShowName();

    delete pear;
    delete banana;
    delete apple;
    delete factory;
}
int main() {
    test01();
    return 0;
}

总结:这个抽象工厂模型其实算是简单工厂模型和工厂方法模型的一个结合 针对产品族和产品等级 其开闭原则是不同的 当我们新增加一个工厂的时候 比如加一个日本工厂 是不需要修改源代码的 符合开闭原则(产品族)  而新增加一个水果 比如西瓜的时候 是需要修改源代码的 不符合开闭原则(产品等级) 所以这就是为什么说抽象工厂模型是针对于产品族而不是产品等级的原因了

你可能感兴趣的:(c++设计模式,c++,开发语言)