设计模式——工厂这一家子

来源:互联网 发布:业余网络兼职 编辑:程序博客网 时间:2024/06/05 18:10

    在《大话设计模式》中,开篇提到的第一个模式就是简单工厂模式,单单理解这个模式我觉得体现不出来它的好处,往后接着看得时候,发现还有工厂方法,再往后发现还有抽象工厂方法,心里有一种兴奋之感,因为既然相似,那么放一起肯定就好理解了。

单单从定义上看,不怎么好理解,定义再加上例子,这样比较着来吧。

    u  简单工厂模式

    简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。

    在类图我们可以看出主要包括三个角色:工厂(Creator)角色、抽象产品(Product)角色、具体产品(Concrete Product)角色。

    u  工厂方法模式

    工厂方法(FactoryMethod)模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。

    在类图我们可以看出主要包括四个角色:抽象工厂(Creator)角色、具体工厂(ConcreteCreator)角色、抽象产品(Product)角色、具体产品(Concrete Product)角色。

    u  抽象工厂模式

    抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态。抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象。

    那我们以具体的实例来比较说明一下吧!

    u  简单工厂模式

用简单工厂模式实现一个计算器的程序代码

using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace ConsoleApplication4{    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()        {            double result=0;            return result ;        }    }    class OperationAdd : Operation   //加减乘除类    {        public override double GetResult()        {            double result = 0;            result = NumberA + NumberB;            return result;        }    }    class OperationSub : Operation    {        public override double GetResult()        {            double result = 0;            result = NumberA - NumberB;            return result;        }    }    class OperationMul : Operation    {        public override double GetResult()        {            double result = 0;            result = NumberA * NumberB;            return result;        }    }    class OperationDiv : Operation    {        public override double GetResult()        {            double result = 0;            if (NumberB == 0)                throw new Exception("除数不能为0。");            result = NumberA / NumberB;            return result;        }    }    class OperationFactory     //简单工厂的实现    {        public static Operation createOperate(string operate)        {            Operation oper = null;            switch (operate)            {                case "+":                    oper = new OperationAdd();                    break;                case "-":                    oper = new OperationSub();                    break;                case "*":                    oper = new OperationMul();                    break;                case "/":                    oper = new OperationDiv();                    break;            }            return oper;        }}

    客户端代码;

客户端代码using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace ConsoleApplication4{    class Program    {        static void Main(string[] args)        {            Operation oper;           简单工厂的实现            oper = OperationFactory.createOperate("+");            oper.NumberA = 1;            oper.NumberB = 2;            double result = oper.GetResult();   }    }}

    u  工厂方法模式

    实现一个计算器

using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace ConsoleApplication4{    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()        {            double result=0;            return result ;        }    }    class OperationAdd : Operation    {        public override double GetResult()        {            double result = 0;            result = NumberA + NumberB;            return result;        }    }    class OperationSub : Operation    {        public override double GetResult()        {            double result = 0;            result = NumberA - NumberB;            return result;        }    }    class OperationMul : Operation    {        public override double GetResult()        {            double result = 0;            result = NumberA * NumberB;            return result;        }    }    class OperationDiv : Operation    {        public override double GetResult()        {            double result = 0;            if (NumberB == 0)                throw new Exception("除数不能为0。");            result = NumberA / NumberB;            return result;        }    }    //class OperationFactory     //简单工厂的实现    //{    //    public static Operation createOperate(string operate)    //    {    //        Operation oper = null;    //        switch (operate)    //        {    //            case "+":    //                oper = new OperationAdd();    //                break;    //            case "-":    //                oper = new OperationSub();    //                break;    //            case "*":    //                oper = new OperationMul();    //                break;    //            case "/":    //                oper = new OperationDiv();    //                break;    //        }    //        return oper;    //    }    //}    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();        }    }}

    客户端代码

using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace ConsoleApplication4{    class Program    {        static void Main(string[] args)        {            //Operation oper;           简单工厂的实现            //oper = OperationFactory.createOperate("+");            //oper.NumberA = 1;            //oper.NumberB = 2;            //double result = oper.GetResult();            IFactory operFactory = new AddFactory();    //工厂的实现            Operation oper = operFactory.CreateOperation();            oper.NumberA = 1;            oper.NumberB = 2;            double result = oper.GetResult();        }    }}

    u  抽象工厂方法

    这个以数据库访问程序为例

using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace ConsoleApplication5{    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("在SQL Server中给User表添加一条记录");        }        public User GetUser(int id)        {            Console.WriteLine("在SQL Server中根据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("在SQL Server中给Department表添加一条记录");        }        public Department GetDepartment(int id)        {            Console.WriteLine("在SQL Server中根据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;        }    }    interface IFactory    {        IUser CreateUser();        IDepartment CreateDepartment();    }    class SqlServerFactory : IFactory    {        public IUser CreateUser()        {            return new SqlserverUser();        }        public IDepartment CreateDepartment()        {            return new SqlserverDepartment();        }    }    class AccessFactory : IFactory    {        public IUser CreateUser()        {            return new AccessUser();        }        public IDepartment CreateDepartment()        {            return new AccessDepartment();        }    }}

    客户端代码

using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace ConsoleApplication5{    class Program    {        static void Main(string[] args)        {            User user = new User();            Department department = new Department();            IFactory factory = new AccessFactory();            IUser iu = factory.CreateUser();            iu.Insert(user);            iu.GetUser(1);            IDepartment id = factory.CreateDepartment();            id.Insert(department);            id.GetDepartment(1);            Console.Read();        }    }}

    比较分析:

      简单工厂模式:

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

例如在例子中,客户端不用管该用哪个类的实例,只要把“+”给工厂,那么工厂就会给出相应的实例。

        缺点:如果需要增加一个新的功能的运算,那么必须去改动运算工厂类的方法的“case”分支的,这样虽然扩展了功能,但是也修改了原来的类,这样可能会一不小心改错某个方法,同样违背了开放-封闭原则。

      工厂方法模式:

        优点:简单工厂模式里工厂类与分支耦合,造成修改时违背了开放-封闭原则,依赖倒转原则,便可以抽象出一个接口。如上例所示,这样工厂方法把简单工厂的内部逻辑判断移到了客户端代码来进行,增加功能修改客户端,而不用修改工厂类,完全实现了“开放-封闭原则”。

        缺点:工厂方法实现时,客户端要决定实例化哪一个工厂来实现运算类,选择判断的问题依然存在。

      抽象工厂模式:

        优点:1、易于交换产品系列。由于是具体工厂类,如上例IFactory factory=new AccessFactory();应用中只需初始化一次,便使得改变一个应用的具体工厂变得容易,即改变不同工厂时使用不同工厂的配置。

              2、分离了具体的类。它使得具体的创建实例过程与客户端分离,客户端是通过他们的抽象接口操作实例。如:IFactory factory=new AccessFactory(),产品的具体类名也被相应的工厂分离,不会出现在客户端中。

        缺点:难易支持新种类的产品。比如要是增加某个东西,那么就需要改动,例如在上例中增加项目表Project,那么需要改动IProject、SqlserverProject、AccessProject三个类,并且也需要改动IFactory下面的两个具体的实例,显然是不方便。此时出现的问题需要简单工厂来改进,但是又会出现问题,我们下篇再讲。

 

    u  小结

    简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。

工厂方法模式是简单工厂模式的衍生,解决了许多简单工厂模式的问题。首先完全实现‘开-闭原则’,实现了可扩展。其次更复杂的层次结构,可以应用于产品结果复杂的场合。

    抽象工厂模式抽象出多个接口,而工厂模式只是抽象抽一个接口,多个抽象接口使得具体类名和具体工厂实现分离,但是这同时也带来不好的地方,那就是新功能的增加使得改动的地方。

    总而言之,一句话,没有一个模式是尽善尽美的,都会存在一定的不足,我们在接触简单工厂时,认为她优于一般的方法,当其中出现不足了,后来看到了工厂模式,工厂模式出现不足了,又出现了抽象工厂模式,而抽象工厂模式的不足,又需要简单工厂的弥补,所谓物极必反,说的也就是这个道理吧,模式之间的相互协调,互补,整合,才能得一个程序变得尽善尽美,一个好的程序设计是这样,人与人之间协调工作也是这样,各尽其力,才能完美。


0 0