23种设计模式(C++)之工厂模式(普通工厂和抽象工厂)
23种设计模式(C++)之工厂模式(普通工厂和抽象工厂)
概述
工厂模式主要分为普通工厂和抽象工厂两种,属于23种设计模式中的创建行设计模式。
下面的意图和适用性部分摘自《设计模式-可复用面向对象软件的基础》一书,其中多条本小白还不能理解,后面只对理解部分进行说明。
意图:
- 普通工厂:定义一个用于创建对象的接口,让子类决定实例化哪个类。Factory Method使一个类的实例化延迟到其子类。
- 抽象工厂:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
适用性:
- 普通工厂:
- 当一个类不知道它所必须创建的对象的类的时候。
- 当一个类希望由它的子类来指定它所创建的对象的时候。
- 当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。
- 抽象工厂:
- 一个系统要独立于它的产品的创建,组合和表示时。
- 一个系统要由多个产品系列中的一个来配置时。
- 当你要强调一系列相关的产品对象的设计以便进行联合使用时。
- 当你提供一个产品类库,而只想显示它们的接口而不是实现时。
C++实例
场景以汽车为例,本例将Car分为电动汽车(Electric Car)和油动汽车(Oil Car)。齿轮(Gear)为两种汽车产品不可或缺的零部件。
定义齿轮抽象类
//Define abstract gear component class
class Gear
{
public:
virtual void getGearInfo() = 0;
};
class ElectricCarGear : public Gear
{
public:
void getGearInfo()
{
std::cout << "I belong to the gear of electric car!\n";
}
};
class OilCarGear : public Gear
{
public:
void getGearInfo()
{
std::cout << "I belong to the gear of oil car!\n";
}
};
无工厂模式
当不采用工厂模式时,Client需要直接实例化不同产品的齿轮类,才能访问其齿轮的Info。
//Client
int main(int argc, char *argv[])
{
//concrete product (no factory)
Gear *electricCarGear = new ElectricCarGear();
Gear *oilCarGear = new OilCarGear();
electricCarGear->getGearInfo();
oilCarGear->getGearInfo();
}
Result:
I belong to the gear of electric car!
I belong to the gear of oil car!
不足:
需要直接访问零部件的类。
普通工厂模式
简单工厂模式由待加工的零件的抽象类和具体的工厂类组成。
基于刚定义的齿轮抽象类,添加具体工厂类:
//Define concrete factory class
//General factory
class Factory
{
public:
Factory() {}
Gear *CreateGear(std::string carType) {
if (carType == "electricCar") {
return new ElectricCarGear();
}
else if (carType == "oilCar")
{
return new OilCarGear();
}
else
{
return NULL;
}
}
};
Client端代码:
//Client
int main(int argc, char *argv[])
{
//concrete factory + abstract component
Factory factory;
Gear *electricCarGear = factory.CreateGear("electricCar");
Gear *oilCarGear = factory.CreateGear("oilCar");
electricCarGear->getGearInfo();
oilCarGear->getGearInfo();
}
Result:
I belong to the gear of electric car!
I belong to the gear of oil car!
优点:
客户端不需要知道电动车的齿轮类和油动车的齿轮类,只需要告诉工厂自己需要什么类型汽车的齿轮,让工厂返回对应类型汽车的齿轮实例即可。
不足:
如果此时增加了油电混合驱动汽车类型,则需要修改Factory类以支持新增汽车类型。
抽象工厂模式
抽象工厂模式由抽象的零部件类和抽象的工厂类组成。抽象工厂类提供了不同类型的汽车工厂的公共接口。
增加产品类型的Case
当添加油电混合驱动汽车类型时,则需要
- 新增Gear的支持该汽车类型的公共接口:
class MixedCarGear :public Gear
{
public:
void getGearInfo()
{
std::cout << "I belong to the gear of mixed car!\n";
}
};
- 新增油电混合驱动汽车工厂的公共接口
【先将普通工厂模式中的concrete工厂类改写为抽象类,再添加新的工厂的接口】
class AbstractFactory
{
public:
virtual Gear *CreateGear() = 0;
};
class ElectricCarFactory : public AbstractFactory
{
public:
Gear *CreateGear()
{
return new ElectricCarGear();
}
};
class OilCarFactory : public AbstractFactory
{
public:
Gear *CreateGear()
{
return new OilCarGear();
}
};
class MixedCarFactory : public AbstractFactory
{
public:
Gear *CreateGear()
{
return new MixedCarGear();
}
};
Client端:
AbstractFactory *electricCarFactory = new ElectricCarFactory();
AbstractFactory *oilCarFactory = new OilCarFactory();
AbstractFactory *mixedCarFactory = new MixedCarFactory();
Gear *electricCarGear = electricCarFactory->CreateGear();
electricCarGear->getGearInfo();
Gear *oilCarGear = oilCarFactory->CreateGear();
oilCarGear->getGearInfo();
Gear *mixedCarGear = mixedCarFactory->CreateGear();
mixedCarGear->getGearInfo();
Result:
I belong to the gear of electric car!
I belong to the gear of oil car!
I belong to the gear of mixed car!
好处:
当需要新增汽车类型时,只需要新增零件的支持该汽车类型的公共接口,以及在抽象工厂类中补充新增汽车类型的公共接口即可
不足:
待补充
增加新组件的Case
当添加新的零部件Bodywork时,定义Bodywork的抽象类:
class Bodywork
{
public:
virtual void getBodyworkInfo() = 0;
};
class ElectricCarBodywork : public Bodywork
{
public:
void getBodyworkInfo()
{
std::cout << "I belong to the bodywork of electric car!\n";
}
};
class OilCarBodywork : public Bodywork
{
public:
void getBodyworkInfo()
{
std::cout << "I belong to the bodywork of oil car!\n";
}
};
定义抽象工厂类:
class AbstractFactory
{
public:
virtual Gear *CreateGear() = 0;
virtual Bodywork *CreateBodywork() = 0;
};
class ElectricCarFactory : public AbstractFactory
{
public:
Gear *CreateGear()
{
return new ElectricCarGear();
}
Bodywork *CreateBodywork()
{
return new ElectricCarBodywork();
}
};
class OilCarFactory : public AbstractFactory
{
public:
Gear *CreateGear()
{
return new OilCarGear();
}
Bodywork *CreateBodywork()
{
return new OilCarBodywork();
}
};
Client端:
//Client
int main(int argc, char *argv[])
{
//abstract factory + abstract components
AbstractFactory *electricCarFactory = new ElectricCarFactory();
AbstractFactory *oilCarFactory = new OilCarFactory();
Gear *electricCarGear = electricCarFactory->CreateGear();
electricCarGear->getGearInfo();
Bodywork *electricCarBodywork = electricCarFactory->CreateBodywork();
electricCarBodywork->getBodyworkInfo();
Gear *oilCarGear = oilCarFactory->CreateGear();
oilCarGear->getGearInfo();
Bodywork *oilCarBodywork = oilCarFactory->CreateBodywork();
oilCarBodywork->getBodyworkInfo();
}
Result:
I belong to the gear of electric car!
I belong to the bodywork of electric car!
I belong to the gear of oil car!
I belong to the bodywork of oil car!
由于本人初学设计模式,如有不足,欢迎指正,万分感谢。