您的位置:首页 > 其它

[.NET 设计模式] Abstract Factory

2007-03-25 17:46 183 查看




类别:创建型
意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
适用:
一个系统要独立于它的产品的创建、组合和表示时。

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

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

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

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

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

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>
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息