• 大话设计模式之工厂模式 C#


    学无止境,精益求精

    十年河东,十年河西,莫欺少年穷

    学历代表你的过去,能力代表你的现在,学习代表你的将来

    大话设计模式一书中第一个开讲的设计模式是简单工厂模式,关于简单工厂模式大家可参考鄙人的博客:代码无错就是优?简单工厂模式 C#

    当然,本篇博客所讲的工厂模式和简单工厂模式还是非常类似的,因此,在进行工厂模式讲解之前,我们有必要重温下简单工厂模式

    何为工厂模式?不论是简单工厂模式还是本篇的工厂模式,其工厂类主要负责生产对象,然后通过相应的对象调用相关的方法

    在重温简单工厂模式之前,我们再次看下简单工厂模式的UML类图

    针对上述的简单工厂模式UML类图,我们得到如下叙述:

    1、简单工厂类是和运算类是有关联的(实线加箭头代表关联),简单工厂类的主要功能是生产运算对象

    2、运算类用斜体表示,说明运算类为抽象类,运算类有两个属性及一个返回值为 double 的方法

    3、加减乘除类继承运算类并实现GetResult()方法。

    针对上述三点叙述,我们可用如下代码来实现(如果你还看不懂UML类图,可以参考鄙人博客:UML类图应该怎么看?

        public class 简单工厂类
        {
            double NumberA, NumberB;
            public 简单工厂类() { }
            public 简单工厂类(double A, double B)
            {
                this.NumberA = A;
                this.NumberB = B;
            }
            double Oper = new double();
            public double Operate(string 符号)
            {
                switch (符号)
                {
                    case "+": Oper = new 加法类().GetResult(NumberA, NumberB); break;
                    case "-": Oper = new 减法类().GetResult(NumberA, NumberB); break;
                    case "*": Oper = new 乘法类().GetResult(NumberA, NumberB); break;
                    case "/": Oper = new 除法类().GetResult(NumberA, NumberB); break;
                }
                return Oper;
            }
        }
    
        public abstract class 运算类
        {
            public abstract double GetResult(double NumberA, double NumberB);
        }
    
        public class 加法类:运算类
        {
            public override double GetResult(double NumberA, double NumberB)
            {
                return NumberA + NumberB;
            }
        }
    
        public class 减法类 : 运算类
        {
            public override double GetResult(double NumberA, double NumberB)
            {
                return NumberA - NumberB;
            }
        }
    
        public class 乘法类 : 运算类
        {
            public override double GetResult(double NumberA, double NumberB)
            {
                return NumberA * NumberB;
            }
        }
    
        public class 除法类 : 运算类
        {
            public override double GetResult(double NumberA, double NumberB)
            {
                if (NumberB != 0)
                    return NumberA / NumberB;
                else throw new Exception("被除数不能为零");
    
            }
        }
    View Code
            static void Main(string[] args)
            {
                double A = 1;
                double B = 2;
                string F = "/";
                简单工厂类 M = new 简单工厂类(A,B);
                double Result =  M.Operate(F);
                Console.WriteLine(Result);
                Console.ReadKey();
            }
    View Code

    上述代码是鄙人看着UML类图自己设计的,和博客:代码无错就是优?简单工厂模式 C# 中的设计代码并不一样!当然,这两种代码都准确的表达的简单工厂的理念。有兴趣的也可以看下 代码无错就是优?简单工厂模式 中的代码实现形式。

    OK,上述就是简单工厂模式的代码设计方案!

    但是简单工厂模式违反了设计模式的开闭原则,所以我们有必要对其进一步优化!

    所谓开闭原则:

    这个原则其实有两个特性,一个是说对于扩展是开放的,另一个是说,对于修改是封闭的(ASD原则

    如何优化呢?

    工厂模式闪亮登场...

    首先看下工厂模式关于加减乘除的UML类图

    额,似乎复杂了很多!

     不急,我们慢慢分析,然后再用代码实现!

    1、运算工厂接口依赖运算类,加法工厂类依赖加法类,减法工厂类依赖减法类,乘法工厂类依赖乘法类,除法工厂类依赖除法类!(虚线加箭头代表依赖)

    2、加减乘除工厂类继承运算工厂接口,加减成熟类继承运算类(三角加实线代表继承)

    3、下方的M的N次方类和对应的工厂类是用来扩展的。

    那么,分析了UML类图的信息,怎样用代码实现呢?

    首先我们来创建左侧部分的五个类(运算类及加减乘除类),如下:

        /// <summary>
        /// 运算类
        /// </summary>
        public class Operation
        {
            public double NumberA, NumberB;
            public virtual double GetResult()
            {
                return 0;
            }
        }
    
        public class Add : Operation
        {
            public override double GetResult()
            {
                return NumberA + NumberB;
            }
        }
    
        public class Sub : Operation
        {
            public override double GetResult()
            {
                return NumberA - NumberB;
            }
        }
    
        public class Mul : Operation
        {
            public override double GetResult()
            {
                return NumberA * NumberB;
            }
        }
    
        public class Div : Operation
        {
            public override double GetResult()
            {
                if (NumberB == 0)
                    throw new Exception("被除数不能为零");
                return NumberA / NumberB;
            }
        }
    View Code

    其次,我们来构建右侧部分的一个接口及四个类(加减乘除工厂类),如下:

        public interface IFactory
        {
            Operation GetOperation();
        }
    
        public class AddFactory : IFactory
        {
            public Operation GetOperation()
            {
                return new Add();
            }
        }
    
        public class SubFactory : IFactory
        {
            public Operation GetOperation()
            {
                return new Sub();
            }
        }
    
        public class MulFactory : IFactory
        {
            public Operation GetOperation()
            {
                return new Mul();
            }
        }
    
        public class DivFactory : IFactory
        {
            public Operation GetOperation()
            {
                return new Div();
            }
        }
    View Code

    客户端代码为:

            static void Main(string[] args)
            {
                IFactory F = new AddFactory();
                Operation AM = F.GetOperation();
                AM.NumberA = 8;
                AM.NumberB = 7;
                double sum = AM.GetResult();
                Console.WriteLine(sum);
                Console.ReadKey();
            }

    最后,我们来运行一下(7+8=15):

    写到这儿,我可以自豪的说:如果你要加平方根运算,我只需新增平方根类及平方根工厂。因此,现在的设计是不违反设计模式的开闭规则的

    我们知道,在简单工厂模式中,我们可以通过运工厂类的 Switch Case 来判断具体的运算类型,但是上述所写的工厂模式却做不到了!这样写无形中加重了客户端的负担(客户端必须自己来判断运算类型),因此:有没有好的办法解决这个弊端呢?

    答案是有,而且还有一个有趣的名字,叫:雷锋工厂

    如何用代码实现呢?

    @陈卧龙的博客

  • 相关阅读:
    【总结】st表
    【luogu】p2024 食物链
    【总结】stl(以后还会慢慢补上
    【总结】二叉堆
    【luogu】p1631 序列合并
    才子们博客地址
    Lemon测评软件使用说明 (对比cena)
    Cena编译器的使用 及任大佬和禚大佬解释(O2优化、C++11特性、开栈)值得大家学习
    编程求100内的素数
    【关于德育和道德方面】
  • 原文地址:https://www.cnblogs.com/chenwolong/p/Factory.html
Copyright © 2020-2023  润新知