zoukankan      html  css  js  c++  java
  • 大话设计模式学习之简单工厂模式与工厂方法模式的学习

    简单工厂模式与工厂方法模式的对比

    简单工厂模式:

    UML图

     

    首先来解释一下这个UML图

    1、运算类是一个基类,包含了两个属性,一个虚方法getResult

    2、加法类,减法类,乘法类,除法类分别继承于基类运算类,并且根据不同的类实例化出不同的虚方法getResult从而实现了多态

    3、简单工厂类继承于运算类,主要封装了业务逻辑,根据不同的操作符实例化出不同的派生类(加法类、减法类、乘法类、除法类)。

    下面是源码分析:

    第一步:创建基类

    #region 基类

        class Operation

        {

            private double _number1;

            private double _number2;

            public double Number1

            {

                get { return this._number1; }

                set { this._number1 = value; }

            }

            public double Number2

            {

                get { return this._number2; }

                set { this._number2 = value; }

            }

            public virtual double getResult()

            {

                double result = 0;

                return result;

            }

        }

    #endregion

    第二步:创建派生类

    #region 四个派生类:加法类,减法类,乘法类,除法类

        class OperationAdd : Operation

        {

            public override double getResult()

            {

                double result = Number1 + Number2;

                return result;

            }

        }

        class OperationSub : Operation

        {

            public override double getResult()

            {

                double result = Number1 - Number2;

                return result;

            }

        }

        class OperationMul : Operation

        {

            public override double getResult()

            {

                double result = Number1 * Number2;

                return result;

            }

        }

        class OperationDiv : Operation

        {

            public override double getResult()

            {

                double result = Number1 / Number2;

                return result;

            }

        }

        #endregion

    第三步:创建简单工厂类

    #region 工厂类

        class OperationFactory : Operation

        {

            public static Operation createOperation(string strOperate)

            {

                Operation oper = null;

                switch (strOperate)

                {

                    case "+":

                        oper = new OperationAdd();

                        break;

                    case "-":

                        oper = new OperationSub();

                        break;

                    case "*":

                        oper = new OperationMul();

                        break;

                    case "/":

                        oper = new OperationDiv();

                        break;

                }

                return oper;

            }

        }

        #endregion

    好啦现在我们在Main函数中使用它们

    class Program

        {

            static void Main(string[] args)

            {

                Console.WriteLine("请输入第一数字");

                string strNumber1 = Console.ReadLine();

                Console.WriteLine("请输入第二个数字");

                string strNumber2 = Console.ReadLine();

                Console.WriteLine("请输入操作符");

                string strOperate = Console.ReadLine();

                Operation oper = OperationFactory.createOperation(strOperate);//实例化对象

                //为实例化的Operation对象传递了两个属性值

                oper.Number1 = double.Parse(strNumber1);

                oper.Number2 = double.Parse(strNumber2);

                double result=oper.getResult();

                Console.WriteLine(result.ToString());

                Console.ReadKey();

            }

          

        }

    运行结果如下:

     

    从我们使用的Main函数我们可以看出,我们并没有任何的业务逻辑结构在里面,只是传递了两个属性变量和一个操作符,而客户端并不需要知道Operation到底做了什么,所有的业务逻辑封装到了Operation类及其派生类中。这样做将业务逻辑层和表现层很好的分离了。注意业务和表现层很好的分离。这是一个很伟大的思想,因为它让我们可以很好的重用这些代码,或者说可维护性很强。比如:网站建设中:后台代码与前台代码的分离,WPF中XAML语言与后台C#逻辑的分离等等。

    好啦,现在我们来看一下比简单工厂更加神奇的工厂方法模式

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

    UML图

     

    如图所示:我们把工厂类抽象为一个接口,这个接口只有一个方法,就是创建抽象产品的工厂方法。然后所有要生成具体类的工厂,就去实现这个接口。

    下面是源码分析:

    第一步:基类设计

        #region 基类

        class Operation

        {

            private double _number1;

            private double _number2;

            public double Number1

            {

                get { return this._number1; }

                set { this._number1 = value; }

            }

            public double Number2

            {

                get { return this._number2; }

                set { this._number2 = value; }

            }

            //创建一个虚方法

            public virtual double getResult()

            {

                double result = 0;

                return result;

            }

        }

    #endregion

    第二步:派生类设计

        #region 派生类继承于基类Operation,并分别重写了虚方法

        class OperationAdd : Operation

        {

            public override double getResult()

            {

                double result = Number1 + Number2;

                return result;

            }

        }

        class OperationSub : Operation

        {

            public override double getResult()

            {

                double result = Number1 - Number2;

                return result;

            }

        }

        class OperationMul : Operation

        {

            public override double getResult()

            {

                double result = Number1 * Number2;

                return result;

            }

        }

        class OperationDiv : Operation

        {

            public override double getResult()

            {

                double result = Number1 / Number2;

                return result;

            }

        }

        #endregion

    第三步:创建一个接口,抽象工厂,所有的派生工厂类都实现这个接口

        #region 抽象工厂

        //创建一个接口

        interface IOperationFactory

        {

            Operation createOperation();

        }

        #endregion

    第四步:派生工厂类设计

    #region 派生工厂类 真正实例化了Operation对象

        //该类为加法工厂类,继承于父类OperationFactory,并实例化createOperation方法并输入OperationAdd对象

        class OperationFactoryAdd : IOperationFactory

        {

            public Operation createOperation()

            {

                return new OperationAdd();

            }

        }

        //该类为减法工厂类,继承于父类OperationFactory,并实例化createOperation方法输出OperationSub对象

        class OperationFactorySub : IOperationFactory

        {

            public Operation createOperation()

            {

                return new OperationSub();

            }

        }

        //该类为乘法工厂类,继承于父类OperationFactory,并实例化createOperation方法输出OperationMul对象

        class OperationFactoryMul : IOperationFactory

        {

            public Operation createOperation()

            {

                return new OperationMul();

            }

        }

        //该类为除法工厂类,继承于父类OperationFactory,并实例化createOperation方法输出OperationDiv对象

        class OperationFactoryDiv : IOperationFactory

        {

            public Operation createOperation()

            {

                return new OperationDiv();

            }

        }

        #endregion

    通过派生的工厂类,我们实际上实例化了Operation对象

    下面我们来看下客户端代码实现:

    class Program

        {

            static void Main(string[] args)

            {

                Console.WriteLine("请输入两个数字");

                string strNumber1 = Console.ReadLine();

                string strNumber2 = Console.ReadLine();

                double douNumber1 = double.Parse(strNumber1);

                double douNumber2 = double.Parse(strNumber2);

                //先实例化一个工厂方法再创建Operation派生对象

                IOperationFactory operFactory = new OperationFactoryAdd();//实例化了一个加法工厂

                Operation objOperation = operFactory.createOperation();//从加法工厂类得到实例的求平均值类

                objOperation.Number1 = douNumber1;//给Operation的两个属性赋值

                objOperation.Number2 = douNumber2;

                //调用getResult方法

                double result=objOperation.getResult();

                Console.WriteLine(result.ToString());

                Console.ReadKey();

            }

        }

    从客户端实现代码我们可以看出 :首先实例化了一个抽象工厂接口,再由实例化得到的工厂类去得到对应的实例化的Operation派生类。

    我们大家可以看到,工厂方法模式与简单工厂模式有着一定的相似性,虽然两者实现了相同的功能(记住千万不要拿实现功能就OK来评价一个程序或者代码设计,那是很不负责的一种态度。而要在功能实现的基础上考虑程序的健壮性,可扩展性,可重用性等)同时工厂方法模式明显比简单工厂模式要复杂的多。那么为什么我们就用简单工厂就可以完成任务行吗?

    好啦,如果我们的需求变了,需要再添加一个功能,比如说求两个数的平均值。

    简单工厂模式的做法是:

    在基类下派生出一个新的类出来,同时必须还要改的一个地方是简单工厂类,在这里面加上一个case的判断,但是这明显是在修改逻辑代码。类的设计原则是不应该修改类的结构或者代码。它违背了Open-Close原则,模式的设计只能对类进行扩展,不能对类进行修改。就好比我们计算机的插槽,CPU只提供了接口,我们要插什么只要在外部插上需要的硬件就行啦,而我们并不能修改CPU里面的结构等其他东西。这就保证了CPU内部工作的稳定性。同样这也是一样的,Open-Close原则也在一定的程度上保证了类设计的稳定性。

    那么如果工厂方法模式的做法是:

    在基类下派生出一个新的类,同时,在抽象工厂中派生出新的工厂方法。这两个类的设计都只是扩展了原有的类或者接口的设计,并没有去修改原有的类或者结构。

    所以工厂方法模式是简单工厂模式的进一步抽象和推广。

    好啦今天就总结到这里:详细内容请大家查阅大话设计模式或者GOF书籍

  • 相关阅读:
    Linux 组与用户
    MYSQL 退出的三个方式
    MYSQL ERROR 1045 (28000): Access denied for user 'neeky'@'Nee' (using password: YES)
    MYSQL 的数据读取方式
    MYSQL alter procedure alter function 它们只可以更改过程的特性,不可以更改过程的逻辑。
    MYSQL this function has none of deterministic no sql ......错误
    gunicorn
    supervisor
    wsgi pep333
    Map,Filter和Reduce
  • 原文地址:https://www.cnblogs.com/luodao1991/p/3058403.html
Copyright © 2011-2022 走看看