定义一个抽象工厂,然后实现若干个子类工厂,用于实例化不同的产品子类对象。
abstract class Factory
{
public ProductA CreateProductA();
public ProductB CreateProductB();
}
class Factory1 : Factory
{
override public ProductA CreateProductA()
{
return new ProductA1();
}
override public ProductB CreateProductB()
{
return new ProductB1();
}
}
class Factory2 : Factory
{
override public ProductA CreateProductA()
{
return new ProductA2();
}
override public ProductB CreateProductB()
{
return new ProductB2();
}
}
调用
Factory factory1 = new Factory1();
ProductA = factory1.CreateProductA();
ProductB = factory1.CreateProductB();
Factory factory2 = new Factory();
ProductA = factory2.CreateProductA();
ProductB = factory2.CreateProductB();
优点
- 现有产品的子类产品扩展方便
比如,ProductA衍生出新的子类产品ProductA3。则只需要扩展一个新的工厂Factory3即可,不需要修改原有的工厂类。
缺点
- 新类型的产品无法扩展,只能修改原有代码
比如新添加一个产品,ProductC。首先需要在抽象工厂Factory中添加接口:
public ProductC CreateProductC();
还要在所有工厂子类中实现这个接口。违背了“开闭原则”。
举例
如果想要封装不同数据库的差异,首先定义了一个抽象数据库工厂类DateBaseFactory,然后定义了基本的接口。之后继承此抽象工厂,实现了不同类型的数据库工厂,DataBaseFactoryMySQL, DataBaseFactoryMongo。
如果现在要支持SQLServer,则非常方便,新添加一个DataBaseFactorySQLServer即可。
但此时要对数据库添加新的操作,则要修改每一个类,添加相对的接口。
改进
从调用具体工厂的代码可以看出,调用者虽然没有与具体的产品类耦合,但却与具体的工厂类耦合了。为了解决这个问题,我们可以使用配置文件,记录要使用的工厂类字符串,然后在代码中使用反射动态创建工厂对象,从而让调用者也与具体的工厂类解藕。
毕竟,修改配置文件,要比修改代码方便的多。