【设计模式】从菜鸟到大鸟之工厂三姐妹


一、全局观

    “编程是一门技术,更是一门艺术!”

    我们说的工厂三姐妹分别是简单工厂模式、工厂方法模式以及抽象工厂模式。它们都属于创建型的设计模式。其实每一个设计模式有且只有一个是核心的地方!只要我们抓住核心,分清楚主次,就可以痛快的使用各种模式了。
二、揭露核心
  *简单工厂模式*
   又叫做静态工厂方法模式(Static Factory Method),不属于23种GOF设计模式之一。
核心是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。
个人理解:简单工厂模式就是要抽象出来一个工厂类,来实例化某个父类的子类。
使用场景:
工厂类负责创建的对象比较少;
客户只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心;

 


 以计算器为例,展示代码:

  

namespace 计算器_简单工厂模式_2015年8月23日
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                
                Console.WriteLine("请输入第一个数字A:");
                int strNumberA = Convert.ToInt32(Console.ReadLine());    

                Console.WriteLine("请输入运算符号:+、-、*、/");
                string strOperation = Console.ReadLine();


                Console.WriteLine("请输入第二个数字B:");
                int strNumberB = Convert.ToInt32(Console.ReadLine());

                Operation oper;                                       //定义一个Operation类的对象oper。
                oper = OperationFactory.createOperate(strOperation);  //获得运算符,调用OperationFactory的方法createOperate。
                oper.NumberA = strNumberA;                            //给NumberA赋值
                oper.NumberB = strNumberB;                            //给NumberB赋值
                double result = oper.GetResult();                     
                Console.WriteLine("您的最终结果为:" + result);
            }
            catch(Exception ex)
            {
                Console.WriteLine("您的输入有错误,原因是:" + ex.Message);
            }

        }
    }
    public class Operation
    {
        private double _numberA =0;    
        private double _numberB =0;

        public double NumberA     //对私有的变量赋值
        {
            get { return _numberA; }
            set { _numberA = value; }
        }
        public double NumberB
        {
            get { return _numberB; }
            set { _numberB = value; }
        }
        public virtual double GetResult()   //定义GetResult方法。
        {
            double result = 0;
            return result;
        }
    }   //运算类
    public class OperationFactory   //简单工厂类  ,用于初始化运算符。
    {
        public static Operation createOperate(string operate)   
        {
            Operation oper=null;          //创建一个operation的类的对象oper,初值为null;
            switch (operate)              //选择实例化到那个类
            {
                case "+" :
                   oper =new OperationAdd();  //实例化加法类
                   break;
                case "-":
                    oper =new OperationDiv();
                   break;
                case "*":
                   oper = new OperationMul();
                   break;
                case "/":
                   oper = new OperationSub();
                   break;
            }
            return oper ;
        }
    }
    public class OperationAdd   : Operation //加法类,继承运算类 
    {
        public override double GetResult()     //继承父类的方法GetResult()
        {
            double result = 0;
            result = NumberA + NumberB;
            return result;
        }
    }
    public class OperationSub   : Operation    //减法类,继承运算类
    {
        public override double GetResult()   //继承父类的方法GetResult()
        {
            double result = 0;
            result = NumberA - NumberB;
            return result ;
        }
    }
    public class OperationMul   : Operation    //乘法类,继承运算类
    {
        public override double GetResult()   // GetResult()方法的覆写 ,运用了virtual和override。
        {
            double result = 0;
            result = NumberA * NumberB;
            return result;
        }
    }
    public class OperationDiv   : Operation    //除法类,继承运算类
    {
        public override double GetResult()    //方法覆用
        {
            double result = 0;
            result = NumberA / NumberB;
            return result ;
        }    
    
    }
}

工厂方法模式(Factory Method)
    工厂方法模式是简单工厂模式的衍生,解决了许多简单工厂模式的问题。定义了一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使用一个类的实例化延迟到子类。
   核心是克服了开放-封闭原则,实现了可拓展,保持了封装对象创建过程的特点。
工厂方法经常用在以下两种情况中:
第一种情况是对于某个产品,调用者清楚地知道应该 使用哪个具体工厂服务 ,实例化该具体工厂,生产出具体的产品来。
第二种情况,只是需要一种产品,而不想知道也不需要知道究竟是哪个工厂为生产的,即 最终选用哪个具体工厂的决定权在生产者一方 ,它们根据当前系统的情况来实例化一个具体的工厂返回给使用者,而这个决策过程这对于使用者来说是透明的。

 

  
抽象工厂(Creator) 角色:是工厂方法模式的 核心 ,与应用程序无关。任何在模式中创建的对象的工厂类必须实现这个接口。
具体工厂(Concrete Creator) 角色:这是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建产品对象。
抽象产品(Product) 角色:工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。在上图中,这个角色是 运算类
具体产品(Concrete Product) 角色:这个角色实现了抽象产品角色所定义的接口。某具体产品有专门的具体工厂创建,它们之间往往一一对应

依旧以计算器为例,展示代码:

//*************************************************************************************
//修改时间:2015年8月30日10:50:22
//地点:501 1号机
//操作人:王雷
//内容:对计算器进行工厂方法模式改造,运用接口,实例运算的结果。
//*********************************************************************************

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace 计算器_工厂方法模式
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                #region 简单工厂客户端代码
                //Console.WriteLine("请输入第一个数字A:");
                //int strNumberA = Convert.ToInt32(Console.ReadLine());

                //Console.WriteLine("请输入运算符号:+、-、*、/");
                //string strOperation = Console.ReadLine();


                //Console.WriteLine("请输入第二个数字B:");
                //int strNumberB = Convert.ToInt32(Console.ReadLine());

                //Operation oper;                                       //定义一个Operation类的对象oper。
                //oper = OperationFactory.createOperate(strOperation);  //获得运算符,调用OperationFactory的方法createOperate。
                //oper.NumberA = strNumberA;                            //给NumberA赋值
                //oper.NumberB = strNumberB;                            //给NumberB赋值
                //double result = oper.GetResult();
                //Console.WriteLine("您的最终结果为:" + result);
#endregion
                  
                IFactory operFactory=new AddFactory ();       //实例化一个加法类的工厂
                Operation oper =operFactory .CreateOperation ();   //一个运算类的,获得加法工厂的方法
                oper .NumberA =4;
                oper .NumberB=5;
                double result =oper .GetResult ();
                Console.WriteLine(result );
            }
            catch (Exception ex)
            {
                Console.WriteLine("您的输入有错误,原因是:" + ex.Message);
            }

        }
    }
    //运算类
    public class Operation
    {
        private double _numberA = 0;
        private double _numberB = 0;

        public double NumberA     //对私有的变量赋值
        {
            get { return _numberA; }
            set { _numberA = value; }
        }
        public double NumberB
        {
            get { return _numberB; }
            set { _numberB = value; }
        }
        public virtual double GetResult()   //定义GetResult方法。
        {
            double result = 0;
            return result;
        }
    }   
    //加法类,继承运算类
    public class OperationAdd : Operation  
    {
        public override double GetResult()     //继承父类的方法GetResult()
        {
            double result = 0;
            result = NumberA + NumberB;
            return result;
        }
    }
    //减法类,继承运算类
    public class OperationSub : Operation    
    {
        public override double GetResult()   //继承父类的方法GetResult()
        {
            double result = 0;
            result = NumberA - NumberB;
            return result;
        }
    }
    //乘法类,继承运算类
    public class OperationMul : Operation    
    {
        public override double GetResult()   // GetResult()方法的覆写 ,运用了virtual和override。
        {
            double result = 0;
            result = NumberA * NumberB;
            return result;
        }
    }
    //除法类,继承运算类
    public class OperationDiv : Operation    
    {
        public override double GetResult()    //方法覆用
        {
            double result = 0;
            result = NumberA / NumberB;
            return result;
        }

    }
    //构建工厂接口
    interface IFactory
    {
        Operation CreateOperation();
    }
    //实现加法接口
    class AddFactory : IFactory
    {
        public Operation CreateOperation()
        {
            return new OperationAdd ();
        }
    }
    //减法类工厂
    class SubFactory : IFactory
    {

        public Operation CreateOperation()
        {
            return new OperationSub() ;
        }
    }
    //乘法类工厂
    class MulFactory : IFactory
    {

        public Operation CreateOperation()
        {
            return new OperationMul ();
        }
    }
    //除法类工厂
    class DivFactory : IFactory
    {

        public Operation CreateOperation()
        {
            return new OperationDiv ();
        }
    }
}


抽象工厂模式( Abstract Factory
    创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类
使用场景:
1. 系统不依赖于产品类实例如何被创建,组合和表达的细节。
2. 系统的产品有多于一个的产品族,而系统只消费其中某一族的产品(抽象工厂模式的原始用意Unix&Windows
Button--->UnixButton/WinButton
Text----->UnixText/WinText
Unix 产品族和Windows 产品族,不会同时使用。
Factory--->UnixFactory/WinFactory
3. 同属于同一个产品族是在一起使用的。这一约束必须在系统的设计中体现出来。
4. 系统提供一个产品类的库,所有产品以同样的接口出现,从而使客户端不依赖于实现。



这次以还数据库为例,展示代码:

//*************************************************************
//时间:2015年9月1日20:56:31
//操作人:王雷
//内容:抽象工厂,可以实例化多个对象。
//
//**********************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace 数据访问程序_抽象工厂模式
{
    class Program
    {
        static void Main(string[] args)
        {
            User user = new User();
            Department dept = new Department();

            IFactory factory = new AccessFactory();

            IUser iu = factory.CreateUser();
            iu.Insert(user);
            iu.GetUser(1);

            IDepartment id = factory.CreateDepartment();
            id.Insert(dept);
            id.GetDepartment(1);

            Console.Read();
        }
    }


    //用户类,声明ID和Name.
    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; }
        }
    }


    //IUser接口,用于客户端的访问,解除与具体数据库访问的耦合。
    interface IUser
    {
        void Insert(User user);
        User GetUser(int id);
    }
    //sql 数据库,实现接口
    class SqlseverUser : IUser
    {
        public void Insert(User user)
        {
            Console.WriteLine("在SQL Sever中给User表添加一条记录");
        }
        public User GetUser(int id)
        {
            Console.WriteLine("在SQL Sever中根据ID得到User表一条记录");
            return null;
        }
    }
    //Access数据库,实现接口
    class AccessUser : IUser
    {
        public void Insert(User user)
        {
            Console.WriteLine("在Access中给User表添加一条记录");
        }

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


    //IFactory接口,定义一个创建访问user表对象的抽象的工厂接口。
    interface IFactory
    {
        IUser CreateUser();
        IDepartment CreateDepartment();  
    }
    //SqlSeverFactory类,实现IFactory接口,实例化Sqlseveruser
    class SqlSeverFactory : IFactory
    {
        public IUser CreateUser()
        {
            return new SqlseverUser();
        }
        public IDepartment CreateDepartment()
        {
            return new SqlseverDepartment();
        }
    }
    //AccessFactory类,实现IFactory接口,实例化Accessuser
    class AccessFactory : IFactory
    {
        public IUser CreateUser()
        {
            return new AccessUser();  //实例化Accessuser
        }
        public IDepartment CreateDepartment()
        {
            return new AccessDepartment ();
        }
    }


    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 ;}
        }
    }
    //IDepartment接口,用于客户端访问,解除与具体数据库访问的耦合。
    interface IDepartment
    {
        void Insert(Department department);
        Department GetDepartment(int id);
    }
    //SqlseverDepartment类,用于访问SQL Sever的Department
    class SqlseverDepartment :IDepartment 
    {
        public void Insert(Department department)
        {
            Console.WriteLine("在SQL Sever中给Department表添加一条记录");
        }
        public Department GetDepartment(int id)
        {
            Console.WriteLine("在SQL Sever中根据ID得到Department表一条记录");
            return null;
        }
    }

    //AccessDepartment类,用于访问Access的Department
    class AccessDepartment : IDepartment
    {
        public void Insert(Department department)
        {
            Console.WriteLine("在Access中给Department表中添加一条记录");
        }
        public Department GetDepartment(int id)
        {
            Console.WriteLine("在Access中根据ID得到Department表中一条记录");
            return null;
        }
    }

}

三、最后小结


     “每一个设计模式,都是一个思想的火花。我们不断积累这些火花,我们就会

燃起熊熊的大火。这些大火,照亮了我们智慧的路。”——米老师。


 通过学习《设计模式》,就要通过对比的方式学习,让我们更加高效率的获得知


识。通过互相碰撞,就可以激起更多的火花。帮助我们高效学习。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 103
    评论
评论 103
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你个佬六

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值