解读设计模式----抽象工厂模式(AbstractFactory Pattern)
一、模式描述
      我的程序中有需要一系列的对象,比如我们要吃一碗米饭(Rice),要喝一杯咖啡(Coffee)......,要想利用他们,我们就必须在程序中根据用户要求,然后一个个调用 new 操作符来生成他们,这样客户程序就要知道相应的类的信息,生成的代码显然不够灵活。那么我们可以在代码中不利用具体的类,而只是说明我们需要什么,然后就能够得到我们想要的对象呢?  
      这当然是可以的,根据GOF在《设计模式》一书里介绍,要创建对象这样的工作应该是属于创建型模式完成的。熟悉各种设计模式意图的朋友就会很快得出结论:“提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类”,至少“无需指定它们具体的类”符合我们的要求。OK,这就是抽象工厂模式的意图。
二、模式意图
      提供一个创建一系列相关或相互依赖对象的接口,而不需指定他们具体的类。
三、模式UML图:                   
               
 
四、模式参与者
  抽象工厂(Abstract Factory)角色:担任这个角色的是工厂方法模式的核心,它是与应用系统商业逻辑无关的。
 抽象工厂(Abstract Factory)角色:担任这个角色的是工厂方法模式的核心,它是与应用系统商业逻辑无关的。 
  具体工厂(Concrete Factory)角色:这个角色直接在客户端的调用下创建产品的实例。这个角色含有选择合适的产品对象的逻辑,而这个逻辑是与应用系统的商业逻辑紧密相关的。
 具体工厂(Concrete Factory)角色:这个角色直接在客户端的调用下创建产品的实例。这个角色含有选择合适的产品对象的逻辑,而这个逻辑是与应用系统的商业逻辑紧密相关的。
  抽象产品(Abstract Product)角色:担任这个角色的类是工厂方法模式所创建的对象的父类,或它们共同拥有的接口。
 抽象产品(Abstract Product)角色:担任这个角色的类是工厂方法模式所创建的对象的父类,或它们共同拥有的接口。
  具体产品(Concrete Product)角色:抽象工厂模式所创建的任何产品对象都是某一个具体产品类的实例。这是客户端最终需要的东西,其内部一定充满了应用系统的商业逻辑。
 具体产品(Concrete Product)角色:抽象工厂模式所创建的任何产品对象都是某一个具体产品类的实例。这是客户端最终需要的东西,其内部一定充满了应用系统的商业逻辑。
五、模式与反射
     利用设计模式可以使我们的代码更灵活,更容易扩展,更容易维护。各种面向对象的程序设计语言都提供了基本相同的机制:比如类、继承、派生、多态等等。但是又有各自的特色,C# 中的反射机制便是一个很重要的工具,好好地利用就可以在实际中发挥很大的作用。
     反射是.NET Framework中的一个非常重要的特性。相信绝大多数的朋友都对其有所了解或是已经熟练的应用这项技术。我们需要根据需求去动态的创建一对象的实例,在程序设计中,通常我们会为了解耦合,把接口的实现对象写入配置文件,让工厂自己去一个特定的地方(配置文件)找他应该要实例化的对象(接口的实现对象),通过这样来实现“依赖注入(Dependency Injection)”。
     本来“依赖注入”需要专门的IOC容器提供,比如Spring.net,Castle这类似的框架产品。而在抽象工厂模式的应用中显然没有这么麻烦,通常的实现就是使用.NET技术‘反射’就可以了。下面是反射的两种常见应用:
应用一:
         Activator.CreateInstance("类型");
应用二:
         Assembly.Load("程序集名称").CreateInstance("命名空间.类名称");
六、抽象工厂的简单实现
 Entity Code
Entity Code
 namespace DesignPattern.AbstractFactory
namespace DesignPattern.AbstractFactory2
 {
{3
 /// <summary>
    /// <summary>4
 /// 抽象产品角色
    /// 抽象产品角色5
 /// </summary>
    /// </summary>6
 public interface INews
    public interface INews7
 {
    {8
 void Insert(News news);
        void Insert(News news);9
 News QueryById(int newsId);
        News QueryById(int newsId);10
 }
    }11

12
 /// <summary>
    /// <summary>13
 /// 具体产品角色
    /// 具体产品角色14
 /// </summary>
    /// </summary>15
 public class NewsSql:INews
    public class NewsSql:INews16
 {
    {17
 public void Insert(News news)
        public void Insert(News news)18
 {
        {19
 Console.WriteLine("插入新闻到SQL数据库");
            Console.WriteLine("插入新闻到SQL数据库");20
 }
        }21

22
 public News QueryById(int newsId)
        public News QueryById(int newsId)23
 {
        {24
 return new News(1, "Hello", " Hello C#!", "beniao");
            return new News(1, "Hello", " Hello C#!", "beniao");25
 }
        }26
 }
    }27

28
 /// <summary>
    /// <summary>29
 /// 具体产品角色
    /// 具体产品角色30
 /// </summary>
    /// </summary>31
 public class NewsAccess : INews
    public class NewsAccess : INews32
 {
    {33
 public void Insert(News news)
        public void Insert(News news)34
 {
        {35
 Console.WriteLine("插入新闻到Access数据库");
            Console.WriteLine("插入新闻到Access数据库");36
 }
        }37

38
 public News QueryById(int newsId)
        public News QueryById(int newsId)39
 {
        {40
 return new News(1, "Hello", " Hello C#!", "beniao");
            return new News(1, "Hello", " Hello C#!", "beniao");41
 }
        }42
 }
    }43
 }
}
 namespace DesignPattern.AbstractFactory
namespace DesignPattern.AbstractFactory2
 {
{3
 /// <summary>
    /// <summary>4
 /// 抽象产品角色
    /// 抽象产品角色5
 /// </summary>
    /// </summary>6
 public interface IUser
    public interface IUser7
 {
    {8
 void Insert(User user);
        void Insert(User user);9
 User QueryById(int userId);
        User QueryById(int userId);10
 }
    }11

12
 /// <summary>
    /// <summary>13
 /// 具体产品角色
    /// 具体产品角色14
 /// </summary>
    /// </summary>15
 public class UserSql:IUser
    public class UserSql:IUser16
 {
    {17
 public void Insert(User user)
        public void Insert(User user)18
 {
        {19
 Console.WriteLine("Insert SQL OK!");
            Console.WriteLine("Insert SQL OK!");20
 }
        }21

22
 public User QueryById(int userId)
        public User QueryById(int userId)23
 {
        {24
 return new User(1, "beniao", "22");
            return new User(1, "beniao", "22");25
 }
        }26
 }
    }27

28
 /// <summary>
    /// <summary>29
 /// 具体产品角色
    /// 具体产品角色30
 /// </summary>
    /// </summary>31
 public class UserAccess : IUser
    public class UserAccess : IUser32
 {
    {33
 public void Insert(User user)
        public void Insert(User user)34
 {
        {35
 Console.WriteLine("Insert Access OK!");
            Console.WriteLine("Insert Access OK!");36
 }
        }37

38
 public User QueryById(int userId)
        public User QueryById(int userId)39
 {
        {40
 return new User(2, "beniao", "23");
            return new User(2, "beniao", "23");41
 }
        }42
 }
    }43
 }
}
 namespace DesignPattern.AbstractFactory
namespace DesignPattern.AbstractFactory2
 {
{3
 /// <summary>
    /// <summary>4
 /// 工厂角色(根据配置文件来确定创建何种对象)
    /// 工厂角色(根据配置文件来确定创建何种对象)5
 /// </summary>
    /// </summary>6
 public class DataAccess
    public class DataAccess7
 {
    {8
 public static IUser CreateUser()
        public static IUser CreateUser()9
 {
        {10
 string obj = ConfigurationManager.AppSettings["usersql"];
            string obj = ConfigurationManager.AppSettings["usersql"];11
 return (IUser)Assembly.Load("DesignPattern.AbstractFactory").CreateInstance(obj);
            return (IUser)Assembly.Load("DesignPattern.AbstractFactory").CreateInstance(obj);12
 }
        }13

14
 public static INews CreateNews()
        public static INews CreateNews()15
 {
        {16
 string obj = ConfigurationManager.AppSettings["newssql"];
            string obj = ConfigurationManager.AppSettings["newssql"];17
 return (INews)Assembly.Load("DesignPattern.AbstractFactory").CreateInstance(obj);
            return (INews)Assembly.Load("DesignPattern.AbstractFactory").CreateInstance(obj);18
 }
        }19
 }
    }20
 ***********************************************************************************
***********************************************************************************21
 /// <summary>
    /// <summary>22
 /// 如果根据GOF的定义及UML图,此为抽象工厂角色
    /// 如果根据GOF的定义及UML图,此为抽象工厂角色23
 /// </summary>
    /// </summary>24
 public class Factory
    public class Factory25
 {
    {26
 public  virtual IUser CreateUser()
        public  virtual IUser CreateUser() 27
 {
        {28
 return null;
            return null;29
 }
        }30

31
 public  virtual INews CreateNews()
        public  virtual INews CreateNews()32
 {
        {33
 return null;
            return null;34
 }
        }35
 }
    }36

37
 /// <summary>
    /// <summary>38
 /// 具体的工厂角色
    /// 具体的工厂角色39
 /// </summary>
    /// </summary>40
 public class SqlFactory:Factory
    public class SqlFactory:Factory41
 {
    {42
 public override IUser CreateUser()
        public override IUser CreateUser()43
 {
        {44
 string obj = ConfigurationManager.AppSettings["usersql"];
            string obj = ConfigurationManager.AppSettings["usersql"];45
 return (IUser)Assembly.Load("DesignPattern.AbstractFactory").CreateInstance(obj);
            return (IUser)Assembly.Load("DesignPattern.AbstractFactory").CreateInstance(obj);46
 }
        }47

48
 public override INews CreateNews()
        public override INews CreateNews()49
 {
        {50
 string obj = ConfigurationManager.AppSettings["newssql"];
            string obj = ConfigurationManager.AppSettings["newssql"];51
 return (INews)Assembly.Load("DesignPattern.AbstractFactory").CreateInstance(obj);
            return (INews)Assembly.Load("DesignPattern.AbstractFactory").CreateInstance(obj);52
 }
        }53
 }
    }54

55
 /// <summary>
    /// <summary>56
 /// 具体的工厂角色
    /// 具体的工厂角色57
 /// </summary>
    /// </summary>58
 public class AccessFactory : Factory
    public class AccessFactory : Factory59
 {
    {60
 public override IUser CreateUser()
        public override IUser CreateUser()61
 {
        {62
 string obj = ConfigurationManager.AppSettings["useracc"];
            string obj = ConfigurationManager.AppSettings["useracc"];63
 return (IUser)Assembly.Load("DesignPattern.AbstractFactory").CreateInstance(obj);
            return (IUser)Assembly.Load("DesignPattern.AbstractFactory").CreateInstance(obj);64
 }
        }65

66
 public override INews CreateNews()
        public override INews CreateNews()67
 {
        {68
 string obj = ConfigurationManager.AppSettings["newsacc"];
            string obj = ConfigurationManager.AppSettings["newsacc"];69
 return (INews)Assembly.Load("DesignPattern.AbstractFactory").CreateInstance(obj);
            return (INews)Assembly.Load("DesignPattern.AbstractFactory").CreateInstance(obj);70
 }
        } 71
 }
    }72
 }
}
 namespace DesignPattern.AbstractFactory
namespace DesignPattern.AbstractFactory2
 {
{3
 class Program
    class Program4
 {
    {5
 static void Main(string[] args)
        static void Main(string[] args)6
 {
        {7
 IUser user = DataAccess.CreateUser();
            IUser user = DataAccess.CreateUser();8
 user.Insert(null);
            user.Insert(null);9

10
 INews news = DataAccess.CreateNews();
            INews news = DataAccess.CreateNews();11
 news.Insert(null);
            news.Insert(null);12

13
 //******************GOF************************
            //******************GOF************************14

15
 Factory factory = new SqlFactory();
            Factory factory = new SqlFactory();16
 factory.CreateNews().Insert(null);
            factory.CreateNews().Insert(null);17
 factory.CreateUser().Insert(null);
            factory.CreateUser().Insert(null);18

19
 factory = new AccessFactory();
            factory = new AccessFactory();20
 factory.CreateNews().Insert(null);
            factory.CreateNews().Insert(null);21
 factory.CreateUser().Insert(null);
            factory.CreateUser().Insert(null);22
 }
        }23
 }
    }24
 }
}          
七、.NET 2.0中的抽象工厂模式
     .NET 2.0相比.NET 1.1有很大的改进,就在ADO.NET上来说吧,提供了一套新的操作接口。下面我就简单的介绍下这套接口的设计,在System.Date下提供了IDbConnection 、IDbCommand、IDbDataAdapter以及IDbTransaction这样一系列接口,通过ProviderFactory来完成具体实现对象的创建,这里就是抽象工厂模式的一个应用。示意性代码:
 public IDbConnection CreateConnection()
public IDbConnection CreateConnection()2
 {
{3
 IDbConnection conn = null;
    IDbConnection conn = null;4
 try
    try5
 {
    {6
 conn = (IDbConnection)Activator.CreateInstance(_connectionTypes[(int)_provider]);
        conn = (IDbConnection)Activator.CreateInstance(_connectionTypes[(int)_provider]);7
 }
    }8
 catch(TargetInvocationException e)
    catch(TargetInvocationException e)9
 {
    {10
 throw new Exception(e.Message);
        throw new Exception(e.Message);11
 }
    }12
 return conn;
    return conn;13
 }
}14

15
 public IDbConnection CreateConnection(string connectionString)
public IDbConnection CreateConnection(string connectionString)16
 {
{17
 IDbConnection conn = null;
    IDbConnection conn = null;18
 object[] param ={ connectionString };
    object[] param ={ connectionString };19
 try
    try20
 {
    {21
 conn = (IDbConnection)Activator.CreateInstance(_connectionTypes[(int)_provider], param);
        conn = (IDbConnection)Activator.CreateInstance(_connectionTypes[(int)_provider], param);22
 }
    }23
 catch (TargetInvocationException e)
    catch (TargetInvocationException e)24
 {
    {25
 throw new Exception(e.Message);
        throw new Exception(e.Message);26
 }
    }27
 return conn;
    return conn;28
 }
}在_connectionTypes数组里存放的是IDbConnection接口的具体实现类型,如下:
 private static Type[] _connectionTypes = new Type[] { typeof(OleDbConnection), typeof(SqlConnection) };
private static Type[] _connectionTypes = new Type[] { typeof(OleDbConnection), typeof(SqlConnection) };由于Command,DataAdapter等对象的代码都和上面很相似,这里就不作过多解释,我把代码贴到下面,有兴趣的看看:
 ProviderFactory
ProviderFactory      关于.NET 2.0的这一知识点不了解的朋友可以下载Web Cast课程进行学习。本文就简单的介绍这些。
七、.NET 2.0中的新ADO.NET操作接口应用示例
     建立一ASP.NET网站项目,在默认的Default.aspx里放置一个GridView控件便OK。这里以MSSQL 2000里的Northwind数据库作为示例数据库,查询出订单表的数据呈现在aspx页面上,进入后台代码文件(.cs文件):
 public partial class _Default : System.Web.UI.Page
public partial class _Default : System.Web.UI.Page 2
 {
{3
 protected void Page_Load(object sender, EventArgs e)
    protected void Page_Load(object sender, EventArgs e)4
 {
    {5
 string connectionString="Data Source=.;Initial Catalog=Northwind;user id=sa;password=;";
        string connectionString="Data Source=.;Initial Catalog=Northwind;user id=sa;password=;";6
 string cmdText = "select * from orders";
        string cmdText = "select * from orders";7

8
 ProviderFactory factory = new ProviderFactory(ProviderType.SqlClient);
        ProviderFactory factory = new ProviderFactory(ProviderType.SqlClient);9
 IDbConnection conn = factory.CreateConnection(connectionString);
        IDbConnection conn = factory.CreateConnection(connectionString);10
 IDbDataAdapter sda = factory.CreateDataAdapter(cmdText, conn);
        IDbDataAdapter sda = factory.CreateDataAdapter(cmdText, conn);11
 DataSet ds = new DataSet();
        DataSet ds = new DataSet();12
 sda.Fill(ds);
        sda.Fill(ds);13
 this.GridView1.DataSource = ds.Tables[0];
        this.GridView1.DataSource = ds.Tables[0];14
 this.GridView1.DataBind();
        this.GridView1.DataBind();15
 }
    }16
 }
}      ProviderFactory担任着工厂的角色,负责创建如IDbConnection、IDbCommand等一系列的产品。如上,我们拿到了工厂角色,通过工厂角色的CreateConnection就创建到了一个基于抽象产品角色IDbConnection接口的实现对象(具体是什么实现对象我们暂不管)。
     .NET 2.0提供了这一套操作接口,对于程序实现上就更加灵活了,更是强调了使用“依赖接口/抽象编程”的思想。 
示例程序代码下载
注:转载请注明出处:http://beniao.cnblogs.com/ 或  http://www.cnblogs.com
由于最近生病精神不振,文章介绍的不是很清楚,望大家体谅。
 
                    
                     
                    
                 
                    
                
 
     
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号