简略工厂模式的弊病

应用简略工厂模式设计零碎,在每次减少新的对象时除了须要新增一个类型以外,还需批改工厂类的代码,违反了开闭准则,而工厂办法模式作为简略工厂模式的延申,恰好补救的简略工厂模式的缺点。

工厂办法模式

对简略工厂模式加以批改,不再提供一个工厂类负责所有对象的创立,而是先定义一个形象的工厂基类,将具体对象的创立过程交给专门的工厂子类去实现,每个工厂子类都继承自形象工厂类,且实现形象工厂类中申明的办法。应用工厂办法模式能够在呈现新的产品时不批改原有的代码,通过新增一个具体的工厂类负责创立该新产品的实例即可,合乎开闭准则。

工厂办法模式的定义:定义一个创建对象的接口,然而让子类决定实例化哪一个对象。工厂办法模式让一个类的实例化提早到其子类。

工厂办法模式的构造

  • Product(形象产品):定义产品的接口,工厂办法模式所创立所有对象类型的基类。
  • ProductA(具体产品类):实现了形象产品的接口,由专门的具体工厂类创立,具体产品和具体工厂关系一一对应。
  • Factory(形象工厂):申明一个Method,返回形象产品类型。形象工厂是工厂办法模式的外围,所有具体工厂类都必须实现形象工厂类的形象办法,返回具体的产品对象。
  • ProductAFactory(具体工厂):形象工厂的子类,实现了形象工厂的办法,返回具体的产品实例。

工厂办法模式的实现

//形象工厂也能够是接口abstract class FactoryMethod{    public abstract Product Build();} //具体工厂类class ProductAFactory : FactoryMethod{    public override Product Build()    {        return new ProductA();    }}// 形象基类abstract class Product{    public void SameMethod()    {        //所有产品的公共办法        Console.WriteLine("所有产品的公共办法");    }    //差异化行为    public abstract void DiffMethod();}//产品Aclass ProductA : Product{    public override void DiffMethod()    {        //这里实现产品A的业务逻辑        Console.WriteLine("这里实现产品A的业务逻辑");    }}
通过配置文件存储具体工厂类名,实现更换新的具体工厂是无需批改源代码
//配置文件<?xml version="1.0" encoding="utf-8" ?><configuration>    <startup>         <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />    </startup>  <appSettings>    <add key="factoryName" value="Factory.ProductAFactory"/>  </appSettings></configuration>static void Main(){    //读取配置文件    var factoryName = ConfigurationManager.AppSettings["factoryName"];    var factoryType = Type.GetType(factoryName);    var factory = Activator.CreateInstance(factoryType) as FactoryMethod;    var product = factory.Build();    product.SameMethod();    product.DiffMethod();    Console.ReadKey();}
运行后果

如果新增产品对象,应用工厂办法模式须要做什么?
  1. 创立新的具体产品类继承形象产品
  2. 创立新的具体工厂类继承形象工厂并实现其办法返回新的产品对象
  3. 批改配置文件,用新增的具体工厂类名替换原有的工厂类名即可
  4. 编译新增的具体产品类和新增的具体工厂类,原有代码无需批改,合乎开闭准则

工厂办法的暗藏

暗藏工厂办法能够进一步简化开发人员对工厂办法的应用,在工厂类中间接调用产品类的业务办法,应用时无需调用工厂办法创建对象,便是工厂办法暗藏,实例代码如下:

//批改后的形象工厂类abstract class FactoryMethod{    public abstract Product Build();    public void DiffMethod()    {        var product = this.Build();        product.DiffMethod();    }}//应用static void Main(){    //读取配置文件    var factoryName = ConfigurationManager.AppSettings["factoryName"];    var factoryType = Type.GetType(factoryName);    var factory = Activator.CreateInstance(factoryType) as FactoryMethod;    //无需创立,间接应用    factory.DiffMethod();    Console.ReadKey();}

工厂办法模式总结

长处
  1. 开发人员只需关怀产品对应的工厂,无需关怀创立细节,对象的创立和应用拆散。
  2. 退出新产品时,无需批改形象工厂和形象产品提供的接口,无需批改原有的代码,只有增加新的产品类和对应的具体工厂类即可,零碎可扩展性良好,完全符合开闭准则。
毛病
  1. 在增加新产品时,须要编写新的具体产品类和具体工厂类,使得类的个数成对减少,减少了零碎的复杂度,更多的类须要编译和运行。
  2. 须要引入形象层,肯定水平减少了零碎的抽象性和了解难度。
什么时候应用?
  1. 应用时不须要晓得具体产品类名,只需晓得对应的工厂就能够,具体产品对象由对应的工厂负责创立,可将具体工厂类的类名存储在配置文件中。
  2. 通过子类决定创立的具体对象,形象工厂只提供接口,子类决定具体创立什么对象,利用面向对象的多态性和里氏代换准则,在运行时,子类对象将笼罩父类对象,使得零碎更加容易扩大,减少灵活性。