文章目录
插图来自: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;
}