你的位置:首页 > ASP.net教程

[ASP.net教程]三种工厂模式(简单工厂、工厂方法、抽象工厂)


一、简单工厂模式

简单工厂模式,提供了一种创建对象的便捷方法。创建者通过不同的类型参数,创建相对应的对象。

实现代码如下:

 public class Product  {    public virtual void Funtion()    {}  }  public class ProductA : Product  {    public override void Funtion()    {      base.Funtion();    }  }  public class ProductB : Product  {    public override void Funtion()    {      base.Funtion();    }  }  public class Creator  {    public static Product Create(string type)    {      switch (type)      {         case "A":          return new ProductA();        case "B":          return new ProductB();        default:          return null;            }    }  }  class Program  {    static void Main(string[] args)    {      Product pa = Creator.Create("A");    }  }

优点:

在创建固定类型的对象时,比较简单好用。

缺点:

1. 在添加对象类型时,需要更改Creator类里面的函数,违反了软件设计中的开闭原则。

2. Creator类依赖于具体类ProductA,和ProductB,在具体类变化时直接影响Creator类,耦合性过强。

工厂模式

         工厂模式将对象的创建延迟到了具体的子类里面实现。这样,我们创建子类对象时,不需要知道具体的子类,只需获取到相应的类型的工厂即可。同时,工厂模式消除了简单工厂方法所具有高耦合性,且满足软件的设计原则。

         工厂模式,解决了创建多个、同类对象的复杂问题。比如我们需要创建100个ProductA种类的对象,如果不使用工厂模式,我们需要new出100个ProductA对象来;通过工厂模式,只需要调用FactoryA多次就能够完成对象的创建。

1. 实现方法

1)工厂模式最常用的结构类图:

实现代码(C#)如下:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace Factory{  public class Product  {    public virtual void Funtion()    { }  }  public class ProductA : Product  {    public override void Funtion()    {      base.Funtion();    }  }  public class ProductB : Product  {    public override void Funtion()    {      base.Funtion();    }  }  public class Factory  {    virtual public Product Create()    {      return null;    }  }  public class FacotryA : Factory  {    public override Product Create()    {      return new ProductA();    }  }  public class FactoryB : Factory  {    public override Product Create()    {      return new ProductB();    }  }  class FactoryMode  {    static void Main(string[] args)    {      FacotryA fa = new FacotryA();      FactoryB fb = new FactoryB();      Product pa = fa.Create();      Product pb = fb.Create();    }  }}

工厂模式的问题在于,每添加一种新的Product必须添加与之相对应的Factory类。比如,现在需要增加一种对象ProductC,同时需要添加FactoryC类来创建ProductC的对象。这样的话,如果需要添加N多种对象,同时就必须添加与之对应的N种工厂类,增加了编码量和繁琐程度,如下图。

2)使用类模板 

         在需要添加多种对象时,采用模版的方式,可以避免创建过多的工厂子类。

此处,只需要定义一个类模板template<class TheProduct> ConcreteFactoy,只要是从Product基类派生的对象类型,都可以通过这个类模板实现。

以下是实现代码(C++).

 

#include "stdafx.h"#include <iostream>using namespace std;class Product{public:  virtual void Function() = 0;};class ProductA : public Product{public:  void Function();};void ProductA::Function(){  cout << "Create ProductA..." << endl;}class Factory{public:  virtual Product* Create() = 0;};template<class TheProduct>class ConcreteFactroy : public Factory{public:  virtual Product* Create();};template<class TheProduct> Product* ConcreteFactroy<TheProduct>::Create(){  return new TheProduct;}int _tmain(int argc, _TCHAR* argv[]){  ConcreteFactroy<ProductA> MyFactory;   Product* pa = MyFactory.Create();  pa->Function();  return 0;}

 

3. 抽象工厂

         抽象工厂模式,用于创建一组相关或独立的对象。通过此模式,用户不需要知道具体的对象类型,只需找到创建的工厂类即可。抽象工厂与工厂方法的区别主要如下:

         工厂方法中的工厂类只能创建一种对象,如FactoryA -> ProductA。

         抽象工厂中的工厂类可以创建多种类型的对象, Factory1 -> {product1, product2, …,productN}

抽象工厂的问题在于,当我们需要添加新的对象AbstractProductC时,需要同时修改AbstractFactory, ConcreteFactory1和ConcreteFactory2三个类。从这个角度来看,我们可以把它先做成一个简单工厂模式,然后在通过反射机制进行改进。通过反射,用户只需要传递product子类型的名字给Factory类。Factory类根据传入的类名字,生成类对象。

以下描述了,抽象工厂模式访问数据库,然后更为简单工厂模式,再使用反射机制的整个过程(摘自《大话设计模式》)。(其实,三种工厂模式都可以使用反射机制来简化对象生成的过程。)

使用抽象工厂访问数据库的类图:

 

我们将抽象工厂更改为简单工厂模式,如下:

使用反射实现(C#),如下:using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Reflection;namespace AbstractFactory{  public interface IUser  {    void InsertUser(IUser user);    IUser GetUser(string user);  }  public class SQLUser : IUser  {    public void InsertUser(IUser user)    {      Console.WriteLine("Access user");    }    public IUser GetUser(string user)    {      return null;    }  }  public class AccessUser : IUser  {    public void InsertUser(IUser user)    {      Console.WriteLine("Access user");    }    public IUser GetUser(string user)    {      return null;    }  }  public class DataAccess  {    private readonly string dbType = "SQL";    public IUser CreateUser()    {      IUser result = null;      switch (dbType)      {        case "SQL":          result = new SQLUser();          break;        case "Access":          result = new AccessUser();          break;        default:          break;      }      return result;    }    public string ReflectType { get; set; }    public IUser CreateUserByReflection()    {      //(IUser)Assembly.Load(当前程序集的名称 "Factory").CreateInstance("命名空间.类名");      return (IUser)Assembly.Load("Factory").CreateInstance(ReflectType);        }  }  class AbstractFactory_Reflect  {    static void Main(string[] args)    {      DataAccess da = new DataAccess();      da.ReflectType = "AbstractFactory.SQLUser";      IUser user = null;      user = da.CreateUserByReflection();      SQLUser sqlUser = user as SQLUser;      if (sqlUser == null)      {        Console.WriteLine("NULL...");      }    }  }}