您的位置:首页 > 其它

[.NET 设计模式] Abstract Factory

2008-09-30 09:17 309 查看




类别:创建型

意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

适用:

一个系统要独立于它的产品的创建、组合和表示时。

一个系统要由多个产品系列中的一个来配置时。

当你要强调一系列相关的产品对象的设计以便进行联合使用时。

当你提供一个产品类库,而只想显示它们的接口而不是实现时。

------------------------

抽象工厂的好处是“提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。”,同时它的缺点也非常明显。

1. 不支持新产品系。

2. 依赖于具体的工厂类。

3. 不能动态(不修改代码)切换产品工厂。

其实问题的核心就是对具体工厂类的依赖,使用工厂方法虽然能方便地在不同工厂间切换,但依然无法支持新产品系。

要解决这个问题,我们可以选择的方案包括:

1. 依赖注入,使用 Castle.Windsor 或者 Spring.NET 等 IoC 容器。

2. 配置反射。

当客户不再依赖具体的工厂类,我们自然可以非常方便地扩充新产品系,基于配置的方式对于动态切换工厂自然也很简单。

1. 配置反射

namespace ConsoleApplication1

{

  interface IProduct

  {

  }

  abstract class AbstractFactory

  {

    public abstract IProduct NewProduct();

    public static AbstractFactory GetFactory()

    {

      string typeName = ConfigurationManager.AppSettings["factory"];

      Type type = Type.GetType(typeName);

      return Activator.CreateInstance(type) as AbstractFactory;

    }

  }

  class ProductA : IProduct

  {

  }

  class FactoryA : AbstractFactory

  {

    public override IProduct NewProduct()

    {

      return new ProductA();

    }

  }

  public class Program

  {

    static void Main(string[] args)

    {

      IProduct p = AbstractFactory.GetFactory().NewProduct();

    }

  }

}

app.Config
<?xml version="1.0" encoding="utf-8" ?>

<configuration>

  <appSettings>

    <add key="factory" value="ConsoleApplication1.FactoryA, ConsoleApplication1"/>

  </appSettings>

</configuration>

这个例子中,我们使用反射动态创建一个具体工厂,从而实现了客户对具体工厂依赖的解耦。由于具体工厂信息存储在配置文件中,因此我们随时都可以切换工厂,当然包括我们新增的工厂和产品系,而无需修改客户代码。

2. IoC

其实从本质上说,IoC所使用的手段和反射基本相同,只是IoC一般提供更强大的配置能力以及生命期管理。多数IoC缺省生命模式就是Singleton,省了我们为工厂提供单件模式的代码。

下面的例子使用了 Castle.Windsor,至于 Spring.NET 也很简单,本贴省略(可以参考本Blog有关Spring.NET的相关文章)。

namespace ConsoleApplication1

{

  interface IProduct

  {

  }

  abstract class AbstractFactory

  {

    public abstract IProduct NewProduct();

    public static AbstractFactory GetFactory()

    {

      IWindsorContainer provider = new WindsorContainer(@"Ioc.xml");

      return provider["factory"] as AbstractFactory;

    }

  }

  class ProductA : IProduct

  {

  }

  class FactoryA : AbstractFactory

  {

    public override IProduct NewProduct()

    {

      return new ProductA();

    }

  }

  public class Program

  {

    static void Main(string[] args)

    {

      IProduct p = AbstractFactory.GetFactory().NewProduct();

    }

  }

}

Ioc.xml
<?xml version="1.0" encoding="utf-8"?>

<configuration>

  <components>

    <component id="factory" type="ConsoleApplication1.FactoryA, ConsoleApplication1">

    </component>

  </components>

</configuration>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: