设计模式之-工厂:简单工厂,工厂方法,抽象工厂

出自 (大话设计模式)

看IOC的时候,有看到方法模式,也不知具体讲的是哪个,索性一把三个复习了遍,做个记录。

简单工厂

   /// <summary>
    /// 运算类
    /// </summary>
    public class Operation
    {       
        //运算虚方法
        public virtual double GetResult()
        {
            return 0;
        }
    }
    /// <summary>
    /// 加法运算类
    /// </summary>
    public class OperationAdd : Operation
    {
        //无参构造
        public OperationAdd() : base() { }
        //加法运算
        public override double GetResult(double A, double B)
        {
            return A + B;
        }
    }
 
    /// <summary>
    /// 减法运算类
    /// </summary>
    public class OperationSub : Operation
    {
        //无参构造
        public OperationSub() : base() { }
        //减法运算
        public override double GetResult(double A, double B)
        {
            return A - B;
        }
    }
 
 
    /// <summary>
    /// 乘法运算类
    /// </summary>
    public class OperationMul : Operation
    {
        //无参构造
        public OperationMul() : base() { }
        //乘法运算
        public override double GetResult(double A, double B)
        {
            return A * B;
        }
    }
 
    /// <summary>
    /// 除法运算类
    /// </summary>
    public class OperationDiv : Operation
    {
        //无参构造
        public OperationDiv() : base() { }
        //除法运算
        public override double GetResult(double A, double B)
        {
            if (B == 0)//除数不能为0
            {
                return 0;
                //throw new Exception("除数不能为0.") //此处应当报错
            }
            return A / B;
        }
    }

大概差不多是这个样子

简单工厂的判断,根据运算符号判断创建那个运算类实体对象如果是 + ,那当然将创建OperationAdd , 以此类推

    //运算类创建工厂
    public class OperationFactory
    {
        public OperationFactory() { }
 
        public static Operation CreateOperation(string Operator)
        {
            /*
            if (Operator == "+")
            {
                return new OperationAdd();
            }
            else if (Operator == "-")
            {
                return new OperationSub();
            }
            else if (Operator == "*")
            {
                return new OperationMul();
            }
            else if (Operator == "/")
            {
                return new OperationDiv();
            }
            else
            {
                return null;
            }
             */
            //另一种方法
            Operation Operation = null;
            switch (Operator)
            {
                case "+":
                    Operation = new OperationAdd();
                    break;
                case "-":
                    Operation = new OperationSub();
                    break;
                case "*":
                    Operation = new OperationMul();
                    break;
                case "/":
                    Operation = new OperationDiv();
                    break;
                default:
                    break;
 
            }
            return Operation;
        }
    }

调用,只传入一个标识“+、-、*、/”,然后在工厂里面判断

        protected void Page_Load(object sender, EventArgs e)
        {
            Operation Operation = OperationFactory.CreateOperation("+");
            Response.Write(Operation.GetResult(12, 11));
        }

 最后面差不多这个样子

 

工厂方法

namespace WebApp
{
    /// <summary>
    /// 运算类
    /// </summary>
    public class Operation
    {
        //运算虚方法
        public virtual double GetResult(double A, double B)
        {
            return 0;
        }
    }
    /// <summary>
    /// 加法运算类
    /// </summary>
    public class OperationAdd : Operation
    {
        //无参构造
        public OperationAdd() : base() { }
        //加法运算
        public override double GetResult(double A, double B)
        {
            return A + B;
        }
    }
 
    /// <summary>
    /// 减法运算类
    /// </summary>
    public class OperationSub : Operation
    {
        //无参构造
        public OperationSub() : base() { }
        //减法运算
        public override double GetResult(double A, double B)
        {
            return A - B;
        }
    }
 
 
    /// <summary>
    /// 乘法运算类
    /// </summary>
    public class OperationMul : Operation
    {
        //无参构造
        public OperationMul() : base() { }
        //乘法运算
        public override double GetResult(double A, double B)
        {
            return A * B;
        }
    }
 
    /// <summary>
    /// 除法运算类
    /// </summary>
    public class OperationDiv : Operation
    {
        //无参构造
        public OperationDiv() : base() { }
        //除法运算
        public override double GetResult(double A, double B)
        {
            if (B == 0)//除数不能为0
            {
                return 0;
                //throw new Exception("除数不能为0.") //此处应当报错
            }
            return A / B;
        }
    }    
 
    //工厂方法接口
    interface IFactory
    {
        Operation CreateOperation();
    }
    //加法工厂
    public class AddFactoty : IFactory
    {
        public Operation CreateOperation()
        {
            return new OperationAdd();
        }
 
    }
    //减法工厂
    public class SubFactory : IFactory
    {
        public Operation CreateOperation()
        {
            return new OperationSub();
        }
    }
    //乘法工厂
    public class MulFactory : IFactory
    {
        public Operation CreateOperation()
        {
            return new OperationMul();
        }
    }
    //除法工厂
    public class DivFactory : IFactory
    {
        public Operation CreateOperation()
        {
            return new OperationDiv();
        }
    }
}

 客户端就已经决定了,到底使用哪个运算类,将逻辑判断从方法工厂内转移了出来

       protected void Page_Load(object sender, EventArgs e)
        {            
            IFactory Factory = new AddFactoty();
            Operation Operation = Factory.CreateOperation();
            Response.Write(Operation.GetResult(12, 11));
        }

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

工厂方法模式实现时,客户端需要决定实例化哪一个工厂来实现运算类,选择判断的问题还是存在的,也就是说,工厂方法把简单工厂的内部逻辑判断移到了客户端代码来进行。

 

抽象工厂

抽象工厂的演变,首先一开始的时候,程序只需满足对SQL数据库的支持

首先有一个用户User类

    //用户类
    public class User
    {
        public int Id { get; set; }
 
        public string Name { get; set; }
    }

 然后呢,有一个对SQL数据操作的类,插入数据 和 读取一条数据

    //SQL数据库操作类
    public class SqlUser
    {
        //数据插入
        public string InsertUser(User user)
        {
            return "往SQL插入一条数据";
        }
        //读取数据
        public string GetUser(int Index)
        {
            return "从SQL中取出一条数据";
        }
    }

 调用

        protected void Page_Load(object sender, EventArgs e)
        {
            //数据库连接操作
            SqlUser sql = new SqlUser();
            //插入一个User
            User user = new User();
            sql.InsertUser(user);
            //读取一条数据
            sql.GetUser(1);
 
        }

 

演变开始了

现在需求变更,需要程序既要支持SQL又支持MySQL,经过思考,利用工厂方法模式,代码变更

 

    #region 用户操作
 
    //用户操作
    public interface IUser
    {
        string InsertUser(User user);
        string GetUser(int index);
    }
    //SQL数据库操作类
    public class SqlUser : IUser
    {
        //数据插入
        public string InsertUser(User user)
        {
            return "往SQL插入一条数据";
        }
 
        //读取数据
        public string GetUser(int index)
        {
            return "从SQL中取出一条数据";
        }
    }
 
    //SQL数据库操作类
    public class MysqlUser : IUser
    {
        //数据插入
        public string InsertUser(User user)
        {
            return "往MySQL插入一条数据";
        }
 
        //读取数据
        public string GetUser(int index)
        {
            return "从MySQL中取出一条数据";
        }
    }
    #endregion
 
    //工厂接口
    public interface IFactory
    {
        IUser CreateUser();
    }
    //Sql 工厂
    public class SqlFactory : IFactory
    {
        public IUser CreateUser()
        {
            return new SqlUser();
        }
    }
 
    //MySql 工厂
    public class SqlFactory : IFactory
    {
        public IUser CreateUser()
        {
            return new MysqlUser();
        }
    }

调用,当应用Sql数据库时候

        protected void Page_Load(object sender, EventArgs e)
        {
            //创建sql工厂
            IFactory factory = new SqlFactory();
            //sql user 的操作
            IUser iuser = factory.CreateUser();
            //插入
            User user = new User();
            Response.Write(iuser.InsertUser(user));
            //读取
            Response.Write(iuser.GetUser(1));
        }

  当使用MySql数据库的时候

        protected void Page_Load(object sender, EventArgs e)
        {
            //创建sql工厂
            IFactory factory = new MySqlFactory();
            //sql user 的操作
            IUser iuser = factory.CreateUser();
            //插入
            User user = new User();
            Response.Write(iuser.InsertUser(user));
            //读取
            Response.Write(iuser.GetUser(1));
        }

只需要改动 IFactory factory = new MySqlFactory();    就行了

如果还要添加Access数据库对User的支持,只要往IUser 和 IFactory 两边各一个就行了

    //Access数据库操作类
    public class AccessUser : IUser
    {
        //数据插入
        public string InsertUser(User user)
        {
            return "往Access插入一条数据";
        }
        //读取数据
        public string GetUser(int index)
        {
            return "从Access中取出一条数据";
        }
    }

 

    //Access
    public class AccessFactory : IFactory
    {
        public IUser CreateUser()
        {
            return new AccessUser();
        }
    }

 

此时不管是添加DB2,还是Oracle数据库对User的支持扩展,都是还是工厂方法的延伸。

但一个数据库里面并不是只有一个User表,肯定还有其他的表,有其他的表,又要对多数据库的支持,那么变换来了

    //部门表
    public class Department
    {
        public int id { get; set; }
        public string DepartmentName { get; set; }
    }

 

为了三个数据库的支持,我们需要

    public interface IDepartment
    {
        //插入
        string InsertDepartmet(Department d);
        //读取
        string GetDepartment(int i);
    }
 
    public class SqlDepartment : IDepartment
    {
        //插入
        public string InsertDepartmet(Department d)
        {
            return "往Sql数据库Department中插入数据";
        }
        //读取
        public string GetDepartment(int i)
        {
            return "从Sql数据库Department读取条数据";
        }
    }
 
    public class MySqlDepartment : IDepartment
    {
        //插入
        public string InsertDepartmet(Department d)
        {
            return "往MySql数据库Department中插入数据";
        }
        //读取
        public string GetDepartment(int i)
        {
            return "从MySql数据库Department读取条数据";
        }
    }
 
    public class AccessDepartment : IDepartment
    {
        //插入
        public string InsertDepartmet(Department d)
        {
            return "往Access数据库Department中插入数据";
        }
        //读取
        public string GetDepartment(int i)
        {
            return "从Access数据库Department读取条数据";
        }
    }

 

然后在工厂里面,添加创建对应的实例

    //工厂接口
    public interface IFactory
    {
        IUser CreateUser();
 
        IDepartment CreateDepartment();
    }
    //Sql 工厂
    public class SqlFactory : IFactory
    {
        public IUser CreateUser()
        {
            return new SqlUser();
        }
        public IDepartment CreateDepartment()
        {
            return new SqlDepartment();
        }
    }
 
    //MySql 工厂
    public class MySqlFactory : IFactory
    {
        public IUser CreateUser()
        {
            return new MysqlUser();
        }
        public IDepartment CreateDepartment()
        {
            return new MySqlDepartment();
        }
    }
 
    //Access
    public class AccessFactory : IFactory
    {
        public IUser CreateUser()
        {
            return new AccessUser();
        }
        public IDepartment CreateDepartment()
        {
            return new AccessDepartment();
        }
    }

 

调用

        protected void Page_Load(object sender, EventArgs e)
        {
            //创建sql工厂
            IFactory factory = new AccessFactory();
            //user
            IUser iuser = factory.CreateUser();
            Response.Write(iuser.InsertUser(new User()));
            Response.Write(iuser.GetUser(1));
            //department
            IDepartment department = factory.CreateDepartment();
            Response.Write(department.InsertDepartmet(new Department()));
            Response.Write(department.GetDepartment(1));
        }

 

唯一的不同

差不多的生成图

有个一个User类和User操作类的时候,是只需要工厂方法模式的,但是数据库中有很多的表,都有各种数据库的支持,所以为了解决这种涉及到多个产品系列的问题,就出现了抽象工厂模式。

 

 

说明:AbstractProductA 和 AbstractProductB 是两个抽象产品,就像上面的User和Department,而ProductA1、ProductA2 和 ProductB1、ProductB2就是对两个产品的具体分类实现。

抽象工厂模式的优点缺点

最大的好处就是易于交换产品系列。IFactory factory = new SqlFactory();这里的最小变动。

创建实例过程和客户端分离,new了之后,你也不知道我做了啥,怎么做的

缺点就是,如果项目新增了表,那...改动的地方不少,有n个数据库的支持,就要创建N+2个实体,还有Factory的相关类都要改动

 

(The end)

 

posted on 2014-12-05 17:20  Aidou_dream  阅读(98)  评论(0)    收藏  举报

导航