工厂设计模式

文章目录

插图来自:https://refactoringguru.cn/design-patterns/catalog


一、简单工厂模式 & 静态工厂模式

简单工厂模式 严格来说并不是一种设计模式,而更像是一种编程习惯。简单工厂模式在创建对象时不会对客户端暴露创建逻辑,而是通过使用一个共同的接口来提供新创建的对象。

当这个提供对象接口被定义为静态方法时,简单工厂模式也被称为静态工厂模式


简单工厂模式包含如下角色:

  • 抽象产品:定义产品规范,描述产品主要特性和功能,是所有具体产品的基类。
  • 具体产品:实现或者继承抽象产品。
  • 具体工厂:提供了创建产品的方法,调用者通过该方法来获取产品。

简单工厂模式优点:

  • 封装了创建对象的过程:当一个调用者想创建一个对象时只需要知道其名称就可以了。
  • 对象创建和业务逻辑被分开:如果要添加新产品只需要修改工厂类,而不需要在原代码中修改,降低了客户代码修改的可能性,在一定程度上增加了代码的可扩展性。

简单工厂模式缺点:增加新产品时需要修改工厂类的代码,违背了开闭原则(对扩展开放,对修改封闭)。

cpp 复制代码
/* 汽车接口 */
class Car {
public:
    virtual void drive() = 0;

    virtual ~Car() = default;
};

/* 轿车 */
class Sedan : public Car {
public:
    void drive() override {
        cout << "Sedan is driving." << endl;
    }
};

/* 卡车 */
class Truck : public Car {
public:
    void drive() override {
        cout << "Truck is driving." << endl;
    }
};

/* 静态工厂类 */
class CarFactory {
public:
    static Car *createCar(const string &carType) {
        if (carType == "Sedan") {
            return new Sedan();
        } else if (carType == "Truck") {
            return new Truck();
        } else {
            return nullptr;
        }
    }
};

int main() {
    unique_ptr<Car> sedan(CarFactory::createCar("Sedan"));
    unique_ptr<Car> truck(CarFactory::createCar("Truck"));

    sedan->drive();
    truck->drive();

    return 0;
}

二、工厂方法模式

工厂方法模式 是一种创建型设计模式,其在父类中提供一个创建对象的方法接口 , 允许子类决定所要实例化对象的类型。工厂方法模式使一个产品类的实例化延迟到工厂的子类中进行。


工厂方法模式包含如下角色:

  • 抽象产品:定义产品规范,描述产品主要特性和功能,是所有具体产品的基类。
  • 具体产品:实现或者继承抽象产品,由具体工厂来创建,与具体工厂之间一一对应。
  • 抽象工厂:提供了创建产品的接口,调用者通用它访问具体工厂的工厂方法来创建产品。
  • 具体工厂:主要是实现抽象工厂中的抽象方法,完成具体产品的创建。

工厂方法模式优点:

  • 用户只需要知道具体工厂的名称就可以得到想要的产品,而无需知道产品的具体创建过程,从而避免了用户和具体产品之间的紧密耦合。
  • 可以将产品创建代码放在程序的单一位置,从而使得代码更容易维护,满足单一职责原则
  • 在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则

工厂方法模式缺点:每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,增加了系统的复杂度

cpp 复制代码
/* 汽车接口 */
class Car {
public:
    virtual void drive() = 0;

    virtual ~Car() = default;
};

/* 工厂接口 */
class CarFactory {
public:
    virtual Car *createCar() = 0;

    virtual ~CarFactory() = default;
};

/* 轿车 */
class Sedan : public Car {
public:
    void drive() override {
        cout << "Sedan is driving." << endl;
    }
};

/* 卡车 */
class Truck : public Car {
public:
    void drive() override {
        cout <<  "Truck is driving." << endl;
    }
};

/* 轿车工厂 */
class SedanFactory : public CarFactory {
public:
    Car *createCar() override {
        return new Sedan();
    }
};

/* 卡车工厂 */
class TruckFactory : public CarFactory {
public:
    Car *createCar() override {
        return new Truck();
    }
};

int main() {
    unique_ptr<CarFactory> sedan_factory(new SedanFactory());
    unique_ptr<CarFactory> truck_factory(new TruckFactory());

    unique_ptr<Car> sedan(sedan_factory->createCar());
    unique_ptr<Car> truck(truck_factory->createCar());

    sedan->drive();
    truck->drive();
    
    return 0;
}

三、抽象工厂模式

抽象工厂模式 是工厂方法模式的升级版本,工厂方法模式只生产某个单一的产品,而抽象工厂模式可生产一系列相关的产品。


抽象工厂模式包含如下角色:

  • 抽象产品:定义产品规范,描述产品主要特性和功能,是所有具体产品的基类。
  • 具体产品 :实现或者继承抽象产品,由具体工厂来创建,与具体工厂之间是多对一的关系。
  • 抽象工厂 :提供了创建产品的接口,调用者通用它访问具体工厂的工厂方法来创建一系列相关的产品。
  • 具体工厂:主要是实现抽象工厂中的抽象方法,完成具体产品的创建。

抽象工厂方法模式优点:

  • 可以确保同一工厂生成的产品相互匹配,比如下例中的福特工厂不会生产出沃尔沃汽车。
  • 可以避免客户端和具体产品代码的耦合。
  • 基于工厂方法模式改进,同样满足单一职责原则和开闭原则

抽象工厂方法模式缺点:代码较为复杂。同时,与工厂方法类似,每当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。比如我们在下面代码中添加一个有关商务车的方法,包括抽象工厂在内的所有工厂类都需要进行修改。

cpp 复制代码
/* 轿车接口 */
class Sedan {
public:
    virtual void drive() = 0;

    virtual ~Sedan() = default;
};

/* 卡车接口 */
class Truck {
public:
    virtual void drive() = 0;

    virtual ~Truck() = default;
};

/* 工厂接口 */
class CarFactory {
public:
    virtual Sedan *createSedan() = 0;

    virtual Truck *createTruck() = 0;

    virtual ~CarFactory() = default;
};

/* 福特轿车 */
class FordSedan : public Sedan {
public:
    void drive() override {
        cout << "Ford sedan is driving." << endl;
    }
};

/* 福特卡车 */
class FordTruck : public Truck {
public:
    void drive() override {
        cout << "Ford Truck is driving." << endl;
    }
};

/* 沃尔沃轿车 */
class VolvoSedan : public Sedan {
public:
    void drive() override {
        cout << "Volvo sedan is driving." << endl;
    }
};

/* 沃尔沃卡车 */
class VolvoTruck : public Truck {
public:
    void drive() override {
        cout << "Volvo Truck is driving." << endl;
    }
};

/* 福特工厂 */
class FordFactory : public CarFactory {
public:
    Sedan *createSedan() override {
        return new FordSedan();
    }

    Truck *createTruck() override {
        return new FordTruck();
    }
};

/* 沃尔沃工厂 */
class VolvoFactory : public CarFactory {
public:
    Sedan *createSedan() override {
        return new VolvoSedan();
    }

    Truck *createTruck() override {
        return new VolvoTruck();
    }
};

int main() {
    unique_ptr<CarFactory> ford_factory = make_unique<FordFactory>();
    unique_ptr<CarFactory> volvo_factory = make_unique<VolvoFactory>();

    unique_ptr<Sedan> ford_sedan(ford_factory->createSedan());
    unique_ptr<Truck> ford_truck(ford_factory->createTruck());
    unique_ptr<Sedan> volvo_sedan(ford_factory->createSedan());
    unique_ptr<Truck> volvo_truck(ford_factory->createTruck());

    ford_sedan->drive();
    ford_truck->drive();
    volvo_sedan->drive();
    volvo_truck->drive();

    return 0;
}
相关推荐
杨充15 小时前
10.可测试性实战设计
设计模式·开源·代码规范
杨充15 小时前
9.重构十二式的实战
设计模式·开源·代码规范
杨充15 小时前
6.设计原则的全景图
设计模式·开源·全栈
杨充15 小时前
2.面向对象的特性
设计模式
杨充15 小时前
7.SOLID原则案例汇
设计模式·开源·全栈
杨充15 小时前
8.反模式与坏味道
设计模式·开源·代码规范
杨充15 小时前
3.接口vs抽象类比较
设计模式
咖啡八杯19 小时前
文法、BNF与AST
java·设计模式·解释器模式·ast·文法
咖啡八杯1 天前
GoF设计模式——解释器模式
java·后端·spring·设计模式