• 工厂模式一般分为简单工厂模式,工厂方法模式,抽象工厂模式。各有优缺点,今天这里还加入了简单工厂模式的另一种实现,添加反射实现简单工厂。 例子  一个很简单的例子:有个富豪想买奔驰,宝马,福特汽车,开...

    引言

            工厂模式是比较常用的设计模式,主要用于返回实例对象,将多种类型的创建集中放在一个地方创建。工厂模式一般分为简单工厂模式,工厂方法模式,抽象工厂模式。各有优缺点,今天这里还加入了简单工厂模式的另一种实现,添加反射实现简单工厂。

    例子

             一个很简单的例子:有个富豪想买奔驰,宝马,福特汽车,开出去玩。

    代码:

    什么模式都不用

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class Client : MonoBehaviour {
        public abstract class Car
        {
            public abstract void Dirve();
        }
        public class Benz : Car
        {
            public override void Dirve()
            {
                Debug.Log("Dirve a Benz");
            }
        }
        public class BMW : Car
        {
            public override void Dirve()
            {
                Debug.Log("Dirve a BMW");
            }
        }
        public class Ford : Car
        {
            public override void Dirve()
            {
                Debug.Log("Dirve a Ford");
            }
        }
    
        void Start () {
            Car car1 = new Benz();
            car1.Dirve();
            Car car2 = new BMW();
            car2.Dirve();
            Car car3 = new Ford();
            car3.Dirve();
        }
    }
    

    上述代码已实现功能,但是上述代码有一些这样的情况:

    1.如果有另一个富豪他也想买这三种车来开,那么在他的类里面也要写这三个类然后new3辆车——代码重复

    2.一个富豪,他里面有三种汽车如何制造出来的代码,作为一个客户,他却要懂生产——职责混淆

    但是,聪明的你肯定马上就想到,直接把这三个汽车类单独抽出来,这样,客户直接new出来就可以了,职责也不混淆,别的富豪要车也可以直接new出来,代码也不重复。

    那我们接下来看,假设我的汽车抽象类,稍微复杂那么一丢丢,如下:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public abstract class Car {
        public float Length;
        public float Width;
        public float High;
        public float MaxSpeed;
        public abstract void Dirve();
        public abstract void Test(); //出厂测试
    }
    

    1.new一辆奔驰车出来,这些字段都需要赋值,还要运行一个出厂测试方法,如果这些赋值,方法在客户client类里面写,那么其他所有客户都要写这些代码,代码重复。

    但是你肯定马上说:“不对,我可以写在汽车类的构造函数里面”,当然可以,不过,如果要干的事情特别多,几十行上百行的代码,全放构造函数里面,有点违背设计原则,在构造函数做太复杂的操作,当出错时发现错误有时会很困难。特别是定义为全局变量时,程序还没有运行、就出错了。构造函数应该尽量简单,一眼望穿,最好能保证永不出现构造失败的情况。

    2.如果Benz(奔驰车)多了一个子类,奔驰二代Benz2,现在买奔驰车返回这个类的对象,那么所有客户端的new Benz(),都要换成new Benz2(),而如果做成工厂模式,直接在返回奔驰车的代码哪里更改一下返回Benz2类的对象就可以了,反正返回的都是Car(抽象父类)——方便维护。

    3.如果所有的汽车类,在返回对象之前,又要添加新的逻辑了,那么需要一个个类的找,修改,如果全集中在工厂类中,直接在工厂类中修改即可,避免遗漏,还是——方便维护。

    所以工厂模式主要是有代码重用,分割职责解耦,便于维护的特点。

     

    那么接下来来看看工厂模式:

    还是上面的例子:有个富豪想买奔驰,宝马,福特汽车,开出去玩。

    一、简单工厂

    汽车类

    public abstract class Car {
        public abstract void Dirve();
    }

    奔驰

    public class Benz : Car{
    
        public override void Dirve()
        {
            Debug.Log("Dirve a Benz");
        }
    }

    宝马

    public class BMW : Car {
        public override void Dirve()
        {
            Debug.Log("Dirve a BMW");
        }
    }

    福特

    public class Ford : Car {
        public override void Dirve()
        {
            Debug.Log("Dirve a Ford");
        }
    }

    简单工厂类

    public class SimpleFactory {
        public static Car CreatCar(string car)
        {
            Car newCar = null;
            if (car == "Benz")
            {
                newCar = new Benz();
            }
            else if (car == "BMW")
            {
                newCar = new BMW();
            }
            else if (car == "Ford")
            {
                newCar = new Ford();
            }
            return newCar;
        }
    }

    客户类

    public class ClientSimple : MonoBehaviour {
    
    	void Start () {
            //简单工厂
            Car car1 = SimpleFactory.CreatCar("Benz");
            car1.Dirve();
            Car car2 = SimpleFactory.CreatCar("BMW");
            car2.Dirve();
            Car car3 = SimpleFactory.CreatCar("Ford"); ;
            car3.Dirve();
        }
    }

    上述代码,客户不需要知道怎么生产汽车(解耦),多个客户要车都可以调用工厂得到汽车,如果汽车初始要做很多事情,都可以在工厂类里面newcar之后调各自类的方法,赋值,如果什么模式都不用,直接new的方式,就要写在类的构造函数里面或者直接在客户类写,不太好(重复)。

    上述代码也会有一些情况,如果我需要新增一种车,比如莱斯莱斯,那么我就要在工厂类里面多加一个else if条件判断。工厂类就要进行修改——扩展性不强,这个工厂类包含类所有类的创建,很重要,频繁改动如果出错影响面广。

    如果种类不多,简单工厂用起来还是不错的。

     

    二、工厂方法

    汽车类同上,

    抽象工厂类:

    public abstract class Factory {
        public abstract Car CreatCar();
    }

    奔驰工厂

    public class BenzFactory : Factory {
        public override Car CreatCar()
        {
            return new Benz();
        }
    }

    宝马工厂

    public class BMWFactory : Factory {
        public override Car CreatCar()
        {
            return new BMW();
        }
    }

    福特工厂

    public class FordFactory : Factory {
        public override Car CreatCar()
        {
            return new Ford();
        }
    }

    客户类

    public class ClientSimple : MonoBehaviour {
    
    	void Start () {
            //工厂方法
            Car car1 = new BenzFactory().CreatCar();
            car1.Dirve();
            Car car2 = new BMWFactory().CreatCar();
            car2.Dirve();
            Car car3 = new FordFactory().CreatCar();
            car3.Dirve();
        }
    }

    上述代码,添加新类型的莱斯莱斯车,需要新增莱斯莱斯车类和莱斯莱斯工厂类,工厂父类Factory不需要修改,这样对于已有的工厂不会产生任何潜在的改动影响——便于扩展。

    对于这种方式,和直接new Benz(), new BMW(), new Ford()有点像,每一种车有一个工厂类,不过还是上面讲的,如果返回一个实例要做很多事情,不好直接写在构造函数里面,可以写在具体的工厂类里面,而且如果工厂父类要添加新的逻辑,所有工厂同时享有。

    工厂方法就是每加一种类型,要添加汽车类,还要添加具体工厂类,增加开销。

     

    三、抽象工厂

    抽象工厂其实就是工厂方法的扩展,以前工厂方法父类,只生产汽车,现在工厂作死新开了一条火箭生产流水线,要可以制作火箭了,那么工厂父类就变成这样:

    public abstract class Factory {
        public abstract Car CreatCar();
        public abstract Rocket CreatRocket();
    }

    那么奔驰工厂,宝马工厂,福特工厂类都要添加生产火箭的方法,奔驰牌火箭,宝马牌火箭,福特牌火箭都属于继承自抽象火箭类Rocket,和之前的Car是一模一样的逻辑。代码就不放了,看这个工厂父类就知道了,这就是抽象工厂和工厂方法的区别。

    这个抽象工厂,如果增加一种新产品种类,工厂父类和所有子类工厂,都需要改动。

    是否使用看自己项目需求了。

     

    四、反射+简单工厂

    public class SimpleFactory {
        public static Car CreatCar(string car)
        {
            Car newCar = null;
            if (car == "Benz")
            {
                newCar = new Benz();
            }
            else if (car == "BMW")
            {
                newCar = new BMW();
            }
            else if (car == "Ford")
            {
                newCar = new Ford();
            }
            return newCar;
        }
    }

    上面的是之前的简单工厂,主要就是不便于扩展,新增一种车,就要在工厂类里面多加一个条件判断。

    现在添加反射实现简单工厂,代码如下:

    public class ReflectionSimpleFactory {
    
        public static Car CreatCar(string carClass)
        {
            //获取当前程序集
            Assembly ass = Assembly.GetCallingAssembly();
            //获取程序集中的类
            Type t = ass.GetType(carClass);
            //创建类的实例对象
            Car o = (Car)Activator.CreateInstance(t);
            return o;
        }	
    }

    客户类还是和之前简单工厂一样调用

    public class ClientSimple : MonoBehaviour {
    
    	void Start () {
            //反射+简单工厂
            Car car1 = ReflectionSimpleFactory.CreatCar("Benz");
            car1.Dirve();
            Car car2 = ReflectionSimpleFactory.CreatCar("BMW");
            car2.Dirve();
            Car car3 = ReflectionSimpleFactory.CreatCar("Ford");
            car3.Dirve();
        }
    }

     

    如果新增一种劳斯莱斯车型,只需要添加新类RR这一个类就可以,工厂类不用做其他改动,解决了简单工厂的扩展性问题。

    public class RR : Car {
        public override void Dirve()
        {
            Debug.Log("Dirve a RR");
        }   
    }
    public class ClientSimple : MonoBehaviour {
    	void Start () {
            //反射+简单工厂
            Car car1 = ReflectionSimpleFactory.CreatCar("Benz");
            car1.Dirve();
            Car car2 = ReflectionSimpleFactory.CreatCar("BMW");
            car2.Dirve();
            Car car3 = ReflectionSimpleFactory.CreatCar("Ford");
            car3.Dirve();
            Car car4 = ReflectionSimpleFactory.CreatCar("RR");
            car4.Dirve();
        }
    }

     

    反射也存在效率问题,我这里创建基本什么都没干,循环创建3辆车,100万次试了一下,测试代码如下:

    using System.Diagnostics;
    using UnityEngine;
    
    public class Client_Factory : MonoBehaviour {
    
    	void Start () {
            Stopwatch st = new Stopwatch();
            st.Reset();
            st.Start();
            for (int i = 0; i < 1000000; i++)
            {
                ////简单工厂
                //Car car1 = SimpleFactory.CreatCar("Benz");
                ////car1.Dirve();
                //Car car2 = SimpleFactory.CreatCar("BMW");
                ////car2.Dirve();
                //Car car3 = SimpleFactory.CreatCar("Ford"); ;
                ////car3.Dirve();
    
                ////工厂方法
                //Car car1 = new BenzFactory().CreatCar();
                ////car1.Dirve();
                //Car car2 = new BMWFactory().CreatCar();
                ////car2.Dirve();
                //Car car3 = new FordFactory().CreatCar();
                ////car3.Dirve();
    
                //反射+简单工厂
                Car car1 = ReflectionSimpleFactory.CreatCar("Benz");
                //car1.Dirve();
                Car car2 = ReflectionSimpleFactory.CreatCar("BMW");
                //car2.Dirve();
                Car car3 = ReflectionSimpleFactory.CreatCar("Ford");
                //car3.Dirve();
            }
            st.Stop();
            UnityEngine.Debug.Log(st.ElapsedMilliseconds.ToString()+ " ms");
        }
    }

    用时分别是简单工厂:237ms,工厂方法:326ms,反射+简单工厂:10305ms,前两种基本差别不大,反射之后差了几十倍。这个类创建很简单,如果类复杂,反射可能更耗时,不过这是100万次,日常开发基本也不太可能调用这么多次,具体是否用,自己项目衡量。

    展开全文
  • 在上一篇博文【C#设计模式-简单工厂模式】中,我们使用简单工厂模式实现了: 如果有一个住户管理系统,里面的住户类型是可变的,每一种租户类型的租金计算公式都存在差异 例如:A类型的住户租金额=天数*单价+绩效*0...

    工厂方法模式简介:

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

    过程方法模式结构:

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

    在上一篇博文【C#设计模式-简单工厂模式】中,我们使用简单工厂模式实现了:

    如果有一个住户管理系统,里面的住户类型是可变的,每一种租户类型的租金计算公式都存在差异
    例如:A类型的住户租金额=天数*单价+绩效*0.005;B类型的住户租金额=月份*(每月价格+performance*0.001)
    这里我们虽然实现了客户的需求,但是如果客户后期需要增加了C类型商店和D类型商店,而它们的算法要求又不一样,
    这个时候我们就需要进行C,D类型商店的创建,并继承Ishop接口,实现里面的方法,
    同时还得继续修改工厂类在switc中增加case进行捕捉创建相应的商店对象,一旦出现这样的情况,是不利于程序的扩展性和项目后期的维护性的。
    现在使用工厂方法模式可以很好的解决这一问题。不多说上代码。

    1.分析:商店有共同的行为特征,都要进行店铺租金计算行为,我们抽象了Ishop ,里面有待实现的计算商店租金方法行为。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace FactoryEntiy
    {
        public interface Ishop
        {
            double Getrent(int days, double dayprice, double performance);
        }
    }

    2.我们实现Isho接口里面的方法,创建A,B类型店铺。

    using FactoryEntiy;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ProductEnity
    {
        /// <summary>
        /// 继承商店接口,实现里面的行为方法,即算法
        /// </summary>
        public class Ashop:Ishop
        {
            /// <summary>
            /// /// A类型商店租金额,天数*单价+绩效*0.005
            /// </summary>
            /// <param name="days">天数</param>
            /// <param name="dayprice">每天单价</param>
            /// <param name="performance">日平均绩效</param>
            /// <returns></returns>
            public double Getrent(int days, double dayprice, double performance)
            {
                Console.WriteLine("A商店的租金算法");
                return days * dayprice + performance * 0.01;
            }
        }
    }

    using FactoryEntiy;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ProductEnity
    {
        /// <summary>
        /// 继承商店接口,实现里面的行为方法,即算法
        /// </summary>
        public class Bshop:Ishop
        {
            /// <summary>
            /// B类型商店的租金=月份*(每月价格+performance*0.001)
            /// </summary>
            /// <param name="month">月数</param>
            /// <param name="monthprice">月单价</param>
            /// <param name="performance">月平均绩效</param>
            /// <returns></returns>
            public double Getrent(int month, double monthprice, double performance)
            {
                Console.WriteLine("B商店的租金算法");
                return month * (monthprice + performance * 0.001);
            }
        }
    }

    3.现在考虑在什么情况下创建商店的实体,对不同的商店进行租金计算,并且方便以后的增加和修改。

    于是我们创建IFactroy接口,里面有待实现的创建商店对象的方法。

    using FactoryEntiy;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace FactoryMethod
    {
        /// <summary>
        /// 工厂类,创建商店类型实体
        /// </summary>
        public interface IFactory
        {
            Ishop CreateShop();
        }
    }
    
    4.现在我们就可以继承自IFactory,实现里面创建对应的商店对象了。

    using FactoryEntiy;
    using FactoryMethod;
    using ProductEnity;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ProductEnity
    {
        /// <summary>
        /// 继承工厂类,创建A类型商店实体
        /// </summary>
        public class CreateBshop : IFactory
        {
            public Ishop CreateShop()
            {
                return new Ashop();
            }
        }
    }
    
    using FactoryEntiy;
    using FactoryMethod;
    using ProductEnity;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ProductEnity
    {
        /// <summary>
        /// 继承工厂类,创建B类型商店实体
        /// </summary>
        public class CreateAshop : IFactory
        {
            public Ishop CreateShop()
            {
                return new Bshop();
            }
        }
    }
    

    5.之后根据当前的商店类型进行判断,该类型的商店应该进行哪一种算法:

    
    

    using FactoryEntiy;
    using System;
    using System.Collections.Generic;
    using System.Configuration;
    using System.Linq;
    using System.Reflection;
    using System.Text;
    
    namespace FactoryMethod.App
    {
        class Program
        {
            static void Main(string[] args)
            {
                string shopname = ConfigurationManager.AppSettings["CreateShopClassName"];
                //shopname为创建商店类名称,此处=CreateAshop
                IFactory af = (IFactory)Assembly.Load("ProductEnity").CreateInstance("ProductEnity." + shopname);
                //第一个ProductEnity是dll的名称,第二个ProductEnity是项目的命名空间。
                Ishop As = af.CreateShop(); double total = As.Getrent(30, 300, 2000); //30 天/100元 日平均绩效为2000 
                Console.WriteLine("该A类型商店的租金为:" + total); 
                
                Console.WriteLine("=============");
                IFactory bf = (IFactory)Assembly.Load("ProductEnity").CreateInstance("ProductEnity." + "CreateBshop");
                //CreateBshop可以保存为配置或者存在数据库中,
                //注意该保存字符串应该与项目中创建的类名一样,
                //否则反射的方式会找不到该项目下的类。
                Ishop Bs = bf.CreateShop(); total = Bs.Getrent(30, 300, 2000); //30 天/100元 日平均绩效为2000
                Console.WriteLine("该A类型商店的租金为:" + total);
            }
        }
    }

    这里我们使用反射的方式创建对象,替换了之前的工厂类通过switch创建对象的方式,有利于后面的新类型商店增加和算法修改增加和维护

    以后在项目需求在有变革,我们只需要重新在项目中增加C,D类型商店,继承Ishop实现里面的方法,同时,添加继承IFactroy接口,创建对应的商店对象编译该项目的

    ProductEnity.dll,以后再进行计算该C,D类型的商店算法就可以通过反射的方式进行计算,不需要修改原来的工程类代码。

    整个项目的结构图如下:



    展开全文
  •  简单工厂工厂方法、抽象工厂都属于设计模式中的创建型模式。其主要功能都是帮助我们把对象的实例化部分抽象取了出来,优化了系统的架构,并且增强了系统的扩展性。此篇博客是笔者对学完这三种模式之后一个小小的...

    引言

            简单工厂、工厂方法、抽象工厂都属于设计模式中的创建型模式。其主要功能都是帮助我们把对象的实例化部分抽象取了出来,优化了系统的架构,并且增强了系统的扩展性。此篇博客是笔者对学完这三种模式之后一个小小的总结

    简单工厂

            简单工厂模式的工厂类一般是使用静态方法,通过接收的参数不同来返回不同的对象实例。不修改代码的话,是无法扩展的


             优点:客户端可以免除直接创建产品对象的责任,而仅仅是“消费”产品。简单工厂模式通过这种做法实现了对责任的分割

             缺点:由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中;它所能创建的类只能是事先考虑到的,如果需要添加新的类,则就需要改变工厂类了

    工厂方法

            工厂方法是针对每一种产品提供一个工厂类。通过不同的工厂实例来创建不同的产品实例。在同一等级结构中,支持增加任意产品


            优点:允许系统在不修改具体工厂角色的情况下引进新产品

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


    抽象工厂

            抽象工厂是应对产品族概念的。应对产品族概念而生,增加新的产品线很容易,但是无法增加新的产品。比如,每个汽车公司可能要同时生产轿车、货车、客车,那么每一个工厂都要有创建轿车、货车和客车的方法


           优点:向客户端提供一个接口,使得客户端在不必指定产品具体类型的情况下,创建多个产品族中的产品对象

           缺点:增加新的产品等级结构很复杂,需要修改抽象工厂和所有的具体工厂类,对“开闭原则”的支持呈现倾斜性

    简单工厂与工厂方法

            工厂方法模式是简单工厂模式的进一步抽象和推广,由于使用了多态性,工厂方法模式保持了简单工厂模式的优点,并且克服了它的缺点,完全符合开闭原则

    工厂方法与抽象工厂

    1、工厂方法

           一个抽象产品类,可以派生出多个具体产品类。一个抽象工厂类,可以派生出多个具体工厂类。每个具体工厂类只能创建一个具体产品类的实例

    2、抽象工厂

            多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。一个抽象工厂类,可以派生出多个具体工厂类。每个具体工厂类可以创建多个具体产品类的实例

    3、工厂方法与抽象工厂的区别

            工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个

    结语

            关于三大工厂模式的代码在这里我就不过多的展示了,晚上有很多初级的教程,大多数都差不多,有需要的可以自行上网搜索。笔者目前只是设计模式的初学者,对于在项目中如何应用这些模式还不是太了解,在后期会进行深入研究,

            本篇文章只是对比着总结了一下三大工厂模式,对于三大工厂模式有一个清晰的认识。通过UML图的变化,也可以看出从简单工厂模式到工厂方法模式再到抽象工厂模式的变化


           本文只是对基础知识做一个小小的总结,不深究。如有不同,见解欢迎指正

           本文所有内容均为作者原创,如有转载,请注明出处


    展开全文
  • 工厂方法模式】 【抽象工厂模式】 第一种:简单工厂模式 一:【简单工厂模式】 简单工厂模式概念(Simple Factory Pattern):定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例...

    《C#设计模式》 三种工厂设计模式

    1. 【简单工厂模式】

    2. 【工厂方法模式】

    3. 【抽象工厂模式】

    第一种:简单工厂模式

    一:【简单工厂模式】

    简单工厂模式概念(Simple Factory Pattern):定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。因为在简单工厂模式中用于创建实例的方法是静态(static)方法,因此简单工厂模式又被称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。

    二: 案例分析

    使用简单工厂模式设计一个可以创建不同几何形状(如圆形、方形和三角形等)的绘图工具,每个几何图形都具有绘制draw()和擦除erase()两个方法;

     首先定义一个接口类;包含两个方法;绘制;擦除;

    
        public interface Draws
        {
            //绘制图形
            void draw();
            //擦除图形
            void erase();
        }

    再在某个具体产品类继承这个Draws接口;以下为三种图形实现方式;

      //==============================================================
        //  作者:zhoupei
        //  时间:2019/2/18 14:12:11
        //  文件名:Circular
        //  版本:V1.0.1  
        //  说明:圆形具体产品类     
        //==============================================================
        class Circular : Draws
        {
            public void draw()
            {
                Console.WriteLine("绘制圆形图形");
            }
            public void erase()
            {
                Console.WriteLine("擦除圆形图形");
            }
    
        }
    
    
     class Rectangle : Draws
        {
            //绘制矩形
            public void draw()
            {
                Console.WriteLine("绘制矩形图形");
            }
            //擦除矩形
            public void erase()
            {
                Console.WriteLine("擦除矩形图形");
            }
        }
    
      class Triangle: Draws
        {
            public void draw()
            {
                Console.WriteLine("绘制三角形图形");
            }
    
            public void erase()
            {
                Console.WriteLine("擦除三角形图形");
            }
        }

    再写个图形处理工厂类,静态工厂方法;

     class FigureFactory
        {
            //静态工厂方法
            public static Draws Getfigure(string figtype)
            {
                Draws dws = null;
                switch (figtype.ToLower())
                {
                    case "rectangle":
                        dws = new Rectangle();
                        break;
                    case "triangle":
                        dws = new Rectangle();
                        break;
                    case "circular":
                        dws = new Rectangle();
                        break;
                    default:
                        dws = null;
                        break;
                }
                return dws;
            }
        }

    客户端调用方法,这里根据读取全局配置文件的方式来获取路径;

    添加app.config文件;配置路径;

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <appSettings>
        <add key="figureType" value="Circular"/>  //传入圆形
      </appSettings>
    </configuration>

    Main函数调用方法;

     static void Main(string[] args)
            {
                Draws dw;
                string figurestr = ConfigurationSettings.AppSettings["figureType"];
                dw = FigureFactory.Getfigure(figurestr);
                dw.draw();//绘制 - 圆形
                dw.erase();//擦除 - 圆形
                Console.ReadLine();
            }

    优缺点总结:

     1. 主要优点

           简单工厂模式的主要优点如下:

           (1) 工厂类包含必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的职责,而仅仅“消费”产品,简单工厂模式实现了对象创建和使用的分离。

           (2) 客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可,对于一些复杂的类名,通过简单工厂模式可以在一定程度减少使用者的记忆量。

           (3) 通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。

             2. 主要缺点

           简单工厂模式的主要缺点如下:

           (1) 由于工厂类集中了所有产品的创建逻辑,职责过重,一旦不能正常工作,整个系统都要受到影响。

           (2) 使用简单工厂模式势必会增加系统中类的个数(引入了新的工厂类),增加了系统的复杂度和理解难度。

           (3) 系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。

           (4) 简单工厂模式由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构。
     

     

    第二种:工厂方法模式

    工厂方法模式概念:工厂方法模式(Factory Method Pattern):定义一个用于创建对象的接口,让子类决定将哪一个类实例化。工厂方法模式让一个类的实例化延迟到其子类。工厂方法模式又简称为工厂模式(Factory Pattern),又可称作虚拟构造器模式(Virtual Constructor Pattern)或多态工厂模式(Polymorphic Factory Pattern)。工厂方法模式是一种类创建型模式。

    案例分析:使用工厂方法模式设计一个程序来读取各种不同类型的图片格式,针对每一种图片格式都设计一个图片读取器,如GIF图片读取器用于读取GIF格式的图片、JPG图片读取器用于读取JPG格式的图片。需充分考虑系统的灵活性和可扩展性。

    首先定义图片接口  即抽象产品类;代码如下!

     /// <summary>
        /// 图片处理接口 
        /// 抽象产品:它是定义产品的接口,是工厂方法模式所创建对象的超类型,也就是产品对象的公共父类。
        /// </summary>
        interface Imager
        {
            void GetImages();
        }

    然后定义抽象工工厂类; 代码如下!

     interface ImagerFactory
        {
            Imager GetImagelist(); //抽象产品工厂类
        }

    现在客户需求里要分别读取处理JPG格式的图片跟GIF格式的图片;

    具体产品类

        //==============================================================
        //  作者:zhoupei
        //  时间:2019/2/18 11:45:23
        //  文件名:GifImg
        //  版本:V1.0.1  
        //  说明:Gif图片 - 具体产品类    
        //==============================================================
        class GifImg : Imager
        {
            public void GetImages()
            {
                Console.WriteLine("读取GIF图片。");
            }
        }
    
        class JpgImg : Imager
        {
            public void GetImages()
            {
                Console.WriteLine("读取Jpg图片。");
            }
        }
    
     

    具体产品工厂

     //==============================================================
        //  作者:zhoupei
        //  时间:2019/2/18 11:46:05
        //  文件名:GifImgFactory
        //  版本:V1.0.1  
        //  说明:产品具体工厂 
        //==============================================================
        class GifImgFactory : ImagerFactory  //继承自抽象产品类
        {
            public Imager GetImagelist()
            {
                Imager im = new GifImg();
                return im;
            }
        } 
        
    
    
        class JpgImgFactory : ImagerFactory
        {
            public Imager GetImagelist()
            {
                Imager im = new JpgImg();
                return im;
            }
        }

    客户端Main()调用: 方式跟以上一样

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <appSettings>
        <add key="imageFactory"  value="FactoryMethod.JpgImgFactory"/>
      </appSettings>
    </configuration>
      static void Main(string[] args)
            {
                ImagerFactory ifc;
                Imager img;
                string factStr = ConfigurationManager.AppSettings["imageFactory"];
                ifc = (JpgImgFactory)Assembly.Load("FactoryMethod").CreateInstance(factStr);
                img = ifc.GetImagelist();
                img.GetImages();
    
                Console.ReadLine();
            }

    工厂方法模式总结:

     1. 主要优点

           工厂方法模式的主要优点如下:

           (1) 在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节,用户只需要关心所需产品对应的工厂,无须关心创建细节,甚至无须知道具体产品类的类名。

           (2) 基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。它能够让工厂可以自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部。工厂方法模式之所以又被称为多态工厂模式,就正是因为所有的具体工厂类都具有同一抽象父类。

           (3) 使用工厂方法模式的另一个优点是在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品就可以了,这样,系统的可扩展性也就变得非常好,完全符合“开闭原则”。

     

          2. 主要缺点

         工厂方法模式的主要缺点如下:

          (1) 在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。

          (2) 由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。

     

    第三中:抽象工厂模式

    抽象工厂模式概述:提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,它是一种对象创建型模式。

    案例分析:某个软件公司欲推出一款新的手机游戏软件,该软件能够支持Symbian、Android和Windows Mobile等多个智能手机操作系统平台,针对不同的手机操作系统,该游戏软件提供了不同的游戏操作控制(OperationController)类和游戏界面控制(InterfaceController)类,并提供相应的工厂类来封装这些类的初始化过程。软件要求具有较好的扩展性以支持新的操作系统平台,为了满足上述需求,试采用抽象工厂模式对其进行设计。

    具体实现:

    //抽象产品类
      interface Android
        {
            void Description();
        }
    
      interface Apple
        {
            void Description();
        } 
    
      interface ASymbian
        {
            void Description();
        }

    抽象工厂类:

    /// <summary>
        /// 游戏支持系统抽象工厂
        /// </summary>
        interface GameFactory
        {
            ASymbian CanRunonSymbian();
            Android CanRunonAndroid();
            Apple CanRunonApple();
        }

    具体产品类

        //==============================================================
        //  作者:zhoupei
        //  时间:2019/2/18 16:08:35
        //  文件名:InterfaceControllerOnAndroid
        //  版本:V1.0.1  
        //  说明:安卓系统支持InterfaceControllerOnAndroid
        //==============================================================
        class InterfaceControllerOnAndroid : Android
        {
            public void Description()
            {
                Console.WriteLine("安卓系统支持InterfaceControllerOnAndroid游戏操作控制");
            }
        }
    
        class InterfaceControllerOnApple : Apple
        {
            public void Description()
            {
                Console.WriteLine("苹果支持 InterfaceController游戏操作控制");
            }
        }
    
        class InterfaceControllerOnSymbian :ASymbian
        {
            public void Description()
            {
                Console.WriteLine("塞班系统支持InterfaceController游戏操作控制");
            }
        }
    
    
    
    
    
        //==============================================================
        //  作者:zhoupei
        //  时间:2019/2/18 16:07:45
        //  文件名:OperationControllerOnAndroid
        //  版本:V1.0.1  
        //  说明:支持OperationController 
        //==============================================================
        class OperationControllerOnAndroid :Android
        {
            public void Description()
            {
                Console.WriteLine("安卓系统支持OperationControllerOnAndroid游戏操作控制");
            }
        }
    
        class OperationControllerOnApple : Apple
        {
            public void Description()
            {
                Console.WriteLine("苹果系统支持OperationController游戏操作控制");
            }
        } 
    
        class OperationControllerOnSymbian : ASymbian
        {
            public void Description()
            {
                Console.WriteLine("塞班系统支持OperationController游戏操作控制");
            }
        }
    
    

    具体工厂类:

        //==============================================================
        //  作者:zhoupei
        //  时间:2019/2/18 16:10:59
        //  文件名:B_InterfaceController
        //  版本:V1.0.1  
        //  说明:
        //==============================================================
        class B_InterfaceController : GameFactory
        {
            public Android CanRunonAndroid()
            {
                return new InterfaceControllerOnAndroid();
            }
    
            public Apple CanRunonApple()
            {
                return new InterfaceControllerOnApple();
            }
    
            public ASymbian CanRunonSymbian()
            {
                return new InterfaceControllerOnSymbian();
            }
    
        }
    
    
        class B_OperationController : GameFactory
        {
            public Android CanRunonAndroid()
            {
                return new OperationControllerOnAndroid();
            }
    
            public Apple CanRunonApple()
            {
                return new OperationControllerOnApple();
            }
    
            public ASymbian CanRunonSymbian()
            {
                return new OperationControllerOnSymbian();
            }
        }

    抽象工厂模式总结

        1. 主要优点

           抽象工厂模式的主要优点如下:

           (1) 抽象工厂模式隔离了具体类的生成,使得客户并不需要知道什么被创建。由于这种隔离,更换一个具体工厂就变得相对容易,所有的具体工厂都实现了抽象工厂中定义的那些公共接口,因此只需改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。

           (2) 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。

           (3) 增加新的产品族很方便,无须修改已有系统,符合“开闭原则”。

     

           2. 主要缺点

           抽象工厂模式的主要缺点如下:

           增加新的产品等级结构麻烦,需要对原有系统进行较大的修改,甚至需要修改抽象层代码,这显然会带来较大的不便,违背了“开闭原则”。

     

     

     

    三种工厂方式学习总结完毕,欢迎指正,讨论指教;

    学习来自我的大学老师《C#设计模式》,感谢恩师;

     

     

     

     

    展开全文
  • 深入理解C#设计模式的简单工厂模式、工厂方法模式和抽象工厂模式 简单工厂模式: 如果我们有一个逻辑,可能需要产生多种对象的时候,我们就将创建对象的过程放在工厂中,我们主程序 的逻辑却不需要修改。例如我们...

    深入理解C#设计模式的简单工厂模式、工厂方法模式和抽象工厂模式

    1. 简单工厂模式:
      如果我们有一个逻辑,可能需要产生多种对象的时候,我们就将创建对象的过程放在工厂中,我们主程序 的逻辑却不需要修改。例如我们输入两个数以及一个操作符来进行运算。
    class OperationSimpleFactory
        {
            static void Main(string[] args)
            {
                Operation oper;
                oper = OperationFactory.CreatOperation("*");
                oper.NumberA = 10;
                oper.NumberB = 5;
                Console.WriteLine(oper.GetResult().ToString());
            }
        }
        class Operation
        {
            private double _numberA;
    
            public double NumberA
            {
                get { return _numberA; }
                set { _numberA = value; }
            }
            private double _numberB;
    
            public double NumberB
            {
                get { return _numberB; }
                set { _numberB = value; }
            }
            public virtual double GetResult()
            {
                double result = 0;
                return result;
            }
        }
        class OpertionAdd : Operation
        {
            public override double GetResult()
            {
                double result = 0;
                result = NumberA + NumberB;
                return result;
            }
        }
        class OpertionSub : Operation
        {
            public override double GetResult()
            {
                double result = 0;
                result = NumberA - NumberB;
                return result;
            }
        }
        class OpertionMul : Operation
        {
            public override double GetResult()
            {
                double result = 0;
                result = NumberA * NumberB;
                return result;
            }
        }
        class OpertionDiv : 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 CreatOperation(string operate)
            {
                Operation oper = null;
                switch (operate)
                {
                    case "+":
                        oper = new OpertionAdd();
                        break;
                    case "-":
                        oper = new OpertionSub();
                        break;
                    case "*":
                        oper = new OpertionMul();
                        break;
                    case "/":
                        oper = new OpertionDiv();
                        break;
                    default:
                        break;
                }
                return oper;
            }
        }
    

    在其中的CreatOperation类中即是我们创建的简单工厂,都过输入运算类型及可返回相应的运算类。简单工厂依赖于运算类即可。即相当于一个工厂生产一个商品的基类,通过内部逻辑实现的子类。
    在这里插入图片描述
    在这里插入图片描述
    简单工厂的应用场景:
    当工厂类负责创建的对象比较少时可以考虑使用简单工厂模式()
    客户如果只知道传入工厂类的参数,对于如何创建对象的逻辑不关心时可以考虑使用简单工厂模式
    2. 工厂方法
    简单工厂模式系统难以扩展,一旦添加新产品就不得不修改简单工厂方法,这样就会造成简单工厂的实现逻辑过于复杂,如果我们想添加一个幂运算就需要修改工厂的静态方法。我们就将工厂抽象。

    class Program
        {
            static void Main(string[] args)
            {
                OperationFactory addFactory = new AddFactory();
                Operation ope = addFactory.create();
                ope.NumberA = 10;
                ope.NumberB = 100;
                Console.WriteLine( ope.GetResult().ToString());
            }
        }
        public class Operation
        {
            private double _numberA;
            public double NumberA
            {
                get { return _numberA; }
                set { _numberA = value; }
            }
            private double _numberB;
            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 OperationMulti : 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;
            }
        }
        public abstract class OperationFactory
        {
            public abstract Operation create();
        }
    
        public class AddFactory : OperationFactory
        {
            public override Operation create()
            {
                return new OperationAdd();
            }
        }
        public class SubFactory : OperationFactory
        {
            public override Operation create()
            {
                return new OperationSub();
            }
        }
        public class MultiFactory : OperationFactory
        {
            public override Operation create()
            {
                return new OperationMulti();
            }
        }
        public class DivFactory : OperationFactory
        {
            public override Operation create()
            {
                return new OperationDiv();
            }
        }
    

    就相当于我将工厂抽象化,对应一个子类工厂实例化一个对象,那么就会有多上个对象就有多少个工厂类,此时如果我想添加一个幂数运算只需要添加一个幂数运算的工厂以及运算类即可。
    在这里插入图片描述
    在这里插入图片描述
    工厂方法模式通过面向对象编程中的多态性来将对象的创建延迟到具体工厂中,从而解决了简单工厂模式中存在的问题,也很好地符合了开放封闭原则(即对扩展开发,对修改封闭)。

    3. 抽象工厂模式
    为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。在现实生活中,一个工厂只创建单个产品这样的例子很少,因为现在的工厂都多元化了,一个工厂创建一系列的产品,如果我们要设计这样的系统时,工厂方法模式显然在这里不适用。一个程序里面一组的对象,比如说,在上面的运算类中,再添加一个菜 的产品;

      class Program
        {
            static void Main(string[] args)
            {
                Factory factory = new AddFactory();
                Operation ope = factory.OperCreate();
                ope.NumberA = 10;
                ope.NumberB = 100;
                Console.WriteLine(ope.GetResult().ToString());
                Food food = factory.FoodCreat();
                food.Cook();
                Console.WriteLine(food.Name);
            }
        }
        public class Operation
        {
            private double _numberA;
            public double NumberA
            {
                get { return _numberA; }
                set { _numberA = value; }
            }
            private double _numberB;
    
            public double NumberB
            {
                get { return _numberB; }
                set { _numberB = value; }
            }
            public virtual double GetResult()
            {
                double result = 0;
                return result;
            }
        }
        public abstract class Food
        {
            private string _name;
    
            public string Name
            {
                get { return _name; }
                set { _name = value; }
            }
            public abstract void Cook();
        }
        public class KongpaoChicken : Food
        {
            public override void Cook()
            {
                Name = "KongpaoChicken";
            }
        }
        public class Manhanquanxi : Food
        {
            public override void Cook()
            {
                Name = "Manhanquanxi";
            }
        }
        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;
            }
        }
        public abstract class Factory
        {
            public abstract Operation OperCreate();
            public abstract Food FoodCreat();
        }
        public class AddFactory : Factory
        {
            public override Operation OperCreate()
            {
                return new OperationAdd();
            }
            public override Food FoodCreat()
            {
                return new Manhanquanxi();
            }
        }
        public class SubFactory : Factory
        {
            public override Operation OperCreate()
            {
                return new OperationSub();
            }
            public override Food FoodCreat()
            {
                return new KongpaoChicken();
            }
        }
    

    通过工厂菜和运算类就紧密的联系了起来。
    抽象工厂模式是工厂方法模式的升级版本,他用来创建一组相关或者相互依赖的对象。
    它与工厂方法模式的区别就在于,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式则是针对的多个产品等级结构。在编程中,通常一个产品结构,表现为一个接口或者抽象类,也就是说,工厂方法模式提供的所有产品都是衍生自同一个接口或抽象类,而抽象工厂模式所提供的产品则是衍生自不同的接口或抽象类。在抽象工厂模式中,有一个产品族的概念:所谓的产品族,是指位于不同产品等级结构中功能相关联的产品组成的家族。抽象工厂模式所提供的一系列产品就组成一个产品族;而工厂方法提供的一系列产品称为一个等级结构。

    在这里插入图片描述

    展开全文
  • 简单工厂方法、工厂方法以及抽象工厂方法的区别
  • 简单工厂方法是由具体执行功能类,工厂类,客户端构成,工厂类有CASE语句,负责创建不同的类,客户端调用工厂类里面的工厂方法,工厂类的工厂方法根据客户端传进去的参数NEW相应的类的对象返回给客户端,客户端得到...
  • 简单工厂模式(工厂方法模式的小弟)简单工厂模式并不属于GoF23个经典设计模式,但通常作为23个设计模式的基础。因为在简单工厂模式中用于创建实例的方法是static方法,所以它也被称为Static Factory Method Pattern....
  • 因为在简单工厂模式中用于创建实例的方法是静态(static)方法,因此简单工厂模式又被称为静态工厂方法模式,它属于类创建型模式。 工厂模式结构图 简单工厂模式角色   在简单工厂模式结构图中包含如下几个角色: ...
  • 一、概念及类图1、简单工厂模式(静态工厂模式) 在简单工厂模式中,工厂类可以根据参数的不同返回不同的类的实例。 2、工厂方法模式(多态模式) 工厂方法模式的核心是抽象工厂类Factory,各种具体工厂类继承抽象...
  • 转发请注明出处:http://blog.csdn.net/qq_28055429/article/details/51628921One----简单工厂模式:一,基本知识:(1)定义:简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不...
  • 关于简单工厂模式,工厂方法模式,抽象工厂模式的一次总结 模式 定义 简单工厂模式 定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。 工厂方法模式 定义一个...
  • 简单工厂模式和工厂方法模式都是实例化对象的模式(或方法)。 区别: 简单工厂模式主要是由工厂对象(确切说是传入工厂类方法的参数)决定实例化哪种对象。如下面代码中的type参数。 public class ...
  • java设计模式,工厂模式、简单工程、工厂方法、抽象工厂
  • 1、简单工厂模式简单工厂模式是属于创建型模式,又叫做静态工厂方法(static Factory Method)模式,简单工厂模式是由一个工厂对象决定创建出来哪一种产品类的实例.简单工厂模式的实质是由一个工厂类根据传入的参数,...
  • 简单工厂:是由一个工厂对象决定创建出哪一种产品类的实例。 A实例调用B实例的方法,称为A依赖于B。如果使用new关键字来创建一个B实例(硬编码耦合),然后调用B实例的方法。一旦系统需要重构:需要使用C类来代替B...
  • 工厂方法模式(Factory Method): 定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类 回顾之前简单工厂 简单工厂的核心代码 class OperationFactory { public ...
  • C#工厂方法模式

    2015-06-09 20:47:48
    简单工厂模式存在一个缺陷即违反了开闭原则。工厂方法模式避免了只一点。 开闭原则定义:一个软件实体应当对扩展开放,对修改关闭。及软件实体应 尽量在不修改原有代码的情况下进行扩展。 开闭原则:...
  • 抽象工厂模式的区别及优缺点及使用场景简单工厂普通简单工厂多方法简单工厂静态方法简单工厂工厂方法模式抽象工厂模式 工厂模式是java设计模式中比较简单的一个设计模式,但很多地方都用到了工厂模式,(如解析xml...
  • 简单工厂模式又 叫静态工厂方法模式(Static FactoryMethod Pattern),是通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。 简单工厂定义一个Factory类,可以根据参数的不同返回不同...
1 2 3 4 5 ... 20
收藏数 281,574
精华内容 112,629
热门标签