学无止境,精益求精html
十年河东,十年河西,莫欺少年穷设计模式
学历表明你的过去,能力表明你的如今,学习表明你的未来ide
大话设计模式一书中第一个开讲的设计模式是简单工厂模式,关于简单工厂模式你们可参考鄙人的博客:代码无错就是优?简单工厂模式 C#学习
固然,本篇博客所讲的工厂模式和简单工厂模式仍是很是相似的,所以,在进行工厂模式讲解以前,咱们有必要重温下简单工厂模式优化
何为工厂模式?不管是简单工厂模式仍是本篇的工厂模式,其工厂类主要负责生产对象,而后经过相应的对象调用相关的方法this
在重温简单工厂模式以前,咱们再次看下简单工厂模式的UML类图spa
针对上述的简单工厂模式UML类图,咱们获得以下叙述:设计
一、简单工厂类是和运算类是有关联的(实线加箭头表明关联),简单工厂类的主要功能是生产运算对象code
二、运算类用斜体表示,说明运算类为抽象类,运算类有两个属性及一个返回值为 double 的方法htm
三、加减乘除类继承运算类并实现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("被除数不能为零"); } }
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(); }
上述代码是鄙人看着UML类图本身设计的,和博客:代码无错就是优?简单工厂模式 C# 中的设计代码并不同!固然,这两种代码都准确的表达的简单工厂的理念。有兴趣的也能够看下 代码无错就是优?简单工厂模式 中的代码实现形式。
OK,上述就是简单工厂模式的代码设计方案!
可是简单工厂模式违反了设计模式的开闭原则,因此咱们有必要对其进一步优化!
所谓开闭原则:
这个原则其实有两个特性,一个是说对于扩展是开放的,另外一个是说,对于修改是封闭的(ASD原则)
如何优化呢?
工厂模式闪亮登场...
首先看下工厂模式关于加减乘除的UML类图
额,彷佛复杂了不少!
不急,咱们慢慢分析,而后再用代码实现!
一、运算工厂接口依赖运算类,加法工厂类依赖加法类,减法工厂类依赖减法类,乘法工厂类依赖乘法类,除法工厂类依赖除法类!(虚线加箭头表明依赖)
二、加减乘除工厂类继承运算工厂接口,加减成熟类继承运算类(三角加实线表明继承)
三、下方的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; } }
其次,咱们来构建右侧部分的一个接口及四个类(加减乘除工厂类),以下:
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(); } }
客户端代码为:
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 来判断具体的运算类型,可是上述所写的工厂模式却作不到了!这样写无形中加剧了客户端的负担(客户端必须本身来判断运算类型),所以:有没有好的办法解决这个弊端呢?
答案是有,并且还有一个有趣的名字,叫:雷锋工厂
如何用代码实现呢?
@陈卧龙的博客