简单工厂、工厂方法与抽象工厂模式对比

    简单工厂模式(不是GoF23种设计模式之一)、工厂方法模式和抽象工厂模式均属于创建型设计模式,它们各有各的优缺点,相互之间有区别也有联系,下面来看看三者之间的对比:

模式名称

定义

优点

缺点

适用范围

简单工厂

由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。

工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。

每增加一个功能,都需要对工厂类的逻辑判断进行修改。

工厂类负责创建的对象比较少,客户只知道传入了工厂类的参数,对于始何创建对象(逻辑)不关心。

工厂方法

定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。

由于使用了多态性,工厂方法克服了简单工厂违背开放-封闭原则的缺点,又保持了封装对象创建过程的优点。

由于每增加一个产品,就需要加一个产品工厂的类,增加了额外的开发量。

当一个类不知道它所必须创建对象的类或一个类希望由子类来指定它所创建的对象时,当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候,可以使用工厂方法。

抽象工厂

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

      1、易于交换产品系列。由于具体工厂类,在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不同的产品配置。

      2、它让具体的创建实例过程与客户端分离,客户端是通过它们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户代码中。

如果需求来自增加功能,此时,需要增加若干类,并修改相关的工厂类。

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

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

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

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


   简单工厂模式UML图
     简单工厂、工厂方法与抽象工厂模式对比_第1张图片
    工厂方法模式UML图
     简单工厂、工厂方法与抽象工厂模式对比_第2张图片
    3、抽象工厂模式UML图
     简单工厂、工厂方法与抽象工厂模式对比_第3张图片
    从上面UML图的演变可以看出,最后的抽象工厂显得非常臃肿。其中的一个解决方法就是将AbstractFactory、ConcreteFactory1和ConcreteFactory2合并为一个DataFactory,而且这三种模式有一种共同的缺点:不能避免分支判断。为了解决这个问题,引入了反射(为了避免修改代码,又引入了配置文件来实现数据访问)这个方法。下面给出抽象工厂方法模式的相关代码(实例参考大话设计模式第15章):
   先给出解决方法的核心代码:
    
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;            //引入反射,必须要写
using System.Configuration;
namespace 抽象工厂模式2用简单工厂来改进抽象工厂
{
    class DataAccess
    {
        #region 未使用反射
        //private static readonly string db = "Sqlserver";  //数据库名称,可替换为Access
        ////private static readonly string db = "Access";

        //public static IUser CreateUser()
        //{
        //    IUser result = null;
        //    switch (db)                                   //由于db的事先设置,所以此处可以根据选择实例化出相应的对象
        //    {
        //        case "Sqlserver":
        //            result = new SqlserverUser();
        //            break;
        //        case "Access":
        //            result = new AccessUser();
        //            break;
        //    }
        //    return result;
        //}

        //public static IDepartment CreateDepartment()
        //{
        //    IDepartment result = null;
        //    switch (db)
        //    {
        //        case "Sqlserver":
        //            result = new SqlserverDepartment();
        //            break;
        //        case "Access":
        //            result = new AccessDepartment();
        //            break;
        //    }
        //    return result;
        //}
        #endregion

        private static readonly string AssemblyName = "抽象工厂模式2用简单工厂来改进抽象工厂";   //AssemblyName就是本解决方案的名称
       
        //只使用反射
        // private static readonly string db = "Sqlserver";
        //private static readlonly string db="Access";                                                                      //数据库名称可以更换为Access
        
        //使用反射+配置文件(使用前需要从引用中添加system.configuration)
        private static readonly string db = ConfigurationManager.AppSettings["DB"];                     //表示读取配置文件

        public static IUser CreateUser()
        {
            string className = AssemblyName + "." + db + "User";
            return (IUser)Assembly.Load(AssemblyName).CreateInstance(className);
        }

        public static IDepartment CreateDepartment()
        {
            string className = AssemblyName + "." + db + "Department";
            return (IDepartment)Assembly.Load(AssemblyName).CreateInstance(className);
        }

    }
}
    然后是各个相关类的代码:
    
 class User
    {
        private int _id;
        public int ID
        {
            get { return _id; }
            set { _id = value; }
        }

        private string _name;
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
    }

    class Department
    {
        private int _id;
        public int ID
        {
            get { return _id; }
            set { _id = value; }
        }

        private string _deptName;
        public string DeptName
        {
            get { return _deptName; }
            set { _deptName = value; }
        }
    }

    interface IUser
    {
        void Insert(User user);

        User GetUser(int id);
    }

    class SqlserverUser : IUser
    {
        public void Insert(User user)
        {
            Console.WriteLine("在Sqlserver中给User表增加一条记录");
        }

        public User GetUser(int id)
        {
            Console.WriteLine("在Sqlserver中根据ID得到User表一条记录");
            return null;
        }
    }

    class AccessUser : IUser
    {
        public void Insert(User user)
        {
            Console.WriteLine("在Access中给User表增加一条记录");
        }

        public User GetUser(int id)
        {
            Console.WriteLine("在Access中根据ID得到User表一条记录");
            return null;
        }
    }

    interface IDepartment
    {
        void Insert(Department department);

        Department GetDepartment(int id);
    }

    class SqlserverDepartment : IDepartment
    {
        public void Insert(Department department)
        {
            Console.WriteLine("在Sqlserver中给Department表增加一条记录");
        }

        public Department GetDepartment(int id)
        {
            Console.WriteLine("在Sqlserver中根据ID得到Department表一条记录");
            return null;
        }
    }

    class AccessDepartment : IDepartment
    {
        public void Insert(Department department)
        {
            Console.WriteLine("在Access中给Department表增加一条记录");
        }

        public Department GetDepartment(int id)
        {
            Console.WriteLine("在Access中根据ID得到Department表一条记录");
            return null;
        }
    }

    最后是客户端代码:
    
            User user = new User();
            Department dept = new Department();

            IUser iu = DataAccess.CreateUser();              //直接得到实际的数据库访问实例,而不存在任何依赖

            iu.Insert(user);
            iu.GetUser(1);

            IDepartment id = DataAccess.CreateDepartment();  //直接得到实际的数据库访问实例,而不存在任何依赖

            id.Insert(dept);
            id.GetDepartment(1);

            Console.Read();
    执行结果:
    
    
    


    

你可能感兴趣的:(简单工厂、工厂方法与抽象工厂模式对比)