学无止境,精益求精

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

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

大话设计模式一书中第一个开讲的设计模式是简单工厂模式,关于简单工厂模式大家可参考鄙人的博客:代码无错就是优?简单工厂模式 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 != )
return NumberA / NumberB;
else throw new Exception("被除数不能为零"); }
}
        static void Main(string[] args)
{
double A = ;
double B = ;
string F = "/";
简单工厂类 M = new 简单工厂类(A,B);
double Result = M.Operate(F);
Console.WriteLine(Result);
Console.ReadKey();
}

上述代码是鄙人看着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 ;
}
} 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 == )
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 = ;
AM.NumberB = ;
double sum = AM.GetResult();
Console.WriteLine(sum);
Console.ReadKey();
}

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

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

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

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

如何用代码实现呢?

@陈卧龙的博客

大话设计模式之工厂模式 C#的更多相关文章

  1. 负载均衡算法,轮询方式 大话设计模式之工厂模式 C#

    负载均衡算法,轮询方式 2018-04-13 17:37 by 天才卧龙, 13 阅读, 0 评论, 收藏, 编辑 学无止境,精益求精 十年河东,十年河西,莫欺少年穷 学历代表你的过去,能力代表你的现 ...

  2. 大话设计模式--抽象工厂模式 Abstract Factory -- C++实现实例

    1. 抽象工厂模式: 提供一个创建一系列相关或者相互依赖对象的接口,而无需指定他们具体的类. 下面是工厂方法模式: 下面是抽象工厂模式: 和工厂方法模式相比 抽象工厂模式可以有多个Product抽象, ...

  3. C#学习之设计模式:工厂模式

    最近研究一下设计模式中工厂模式的应用,在此记录如下: 什么是工厂模式? 工厂模式属于设计模式中的创造型设计模式的一种.它的主要作用是协助我们创建对象,为创建对象提供最佳的方式.减少代码中的耦合程度,方 ...

  4. linkin大话设计模式--抽象工厂

    linkin大话设计模式--抽象工厂 在前面讲到的简单工厂里面虽然实现了我们那个类和其中的依赖的解耦,但是在产生我们需要的依赖的那个工厂里面还是和具体的产品类耦合了  现在要是还想彻底解耦的话怎么办呢 ...

  5. 设计模式之工厂模式(c++)

    问题描述 在面向对象系统设计中经常可以遇到以下的两类问题:1)为了提高内聚(Cohesion)和松耦合(Coupling),我们经常会抽象出一些类的公共接口以形成抽象基类或者接口.这样我们可以通过声明 ...

  6. C# Json反序列化 C# 实现表单的自动化测试<通过程序控制一个网页> 验证码处理类:UnCodebase.cs + BauDuAi 读取验证码的值(并非好的解决方案) 大话设计模式:原型模式 C# 深浅复制 MemberwiseClone

    C# Json反序列化   Json反序列化有两种方式[本人],一种是生成实体的,方便处理大量数据,复杂度稍高,一种是用匿名类写,方便读取数据,较为简单. 使用了Newtonsoft.Json,可以自 ...

  7. python 设计模式之工厂模式 Factory Pattern (简单工厂模式,工厂方法模式,抽象工厂模式)

    十一回了趟老家,十一前工作一大堆忙成了狗,十一回来后又积累了一大堆又 忙成了狗,今天刚好抽了一点空开始写工厂方法模式 我看了<Head First 设计模式>P109--P133 这25页 ...

  8. 设计模式——抽象工厂模式及java实现

    设计模式--抽象工厂模式及java实现 设计模式在大型软件工程中很重要,软件工程中采用了优秀的设计模式有利于代码维护,方便日后更改和添加功能. 设计模式有很多,而且也随着时间在不断增多,其中最著名的是 ...

  9. 5. 星际争霸之php设计模式--抽象工厂模式

    题记==============================================================================本php设计模式专辑来源于博客(jymo ...

随机推荐

  1. recovery 恢复出厂设置失败Data wipe failed

    最近客户反馈,编译32位的android系统,在recovery中执行恢复出厂设置的时候失败了,失败的打印提升信息如下. Formatting /data... [ 2.191404] E:get_f ...

  2. python第四十二天 socket ---ssh

    用scoket 写一个简版的ssh 服务端: #!usr/bin/env python #-*-coding:utf-8-*- # Author calmyan import socket,os s= ...

  3. MySQL复制ERROR 1794 (HY000): Slave is not configured or failed to initialize properly.

    ERROR 1794 (HY000): Slave is not configured or failed to initialize properly. You must at least set  ...

  4. flask框架的教程--程序的基本结构[二]

    一个简单的程序 from flask import Flask # 实例化app 对象 app = Flask(__name__) @app.route('/') def index(): retur ...

  5. February 4th, 2018 Week 6th Sunday

    Hope clouds observation. 心怀希望会蒙蔽双眼,影响判断. Almost every of us thinks we would be the master of our liv ...

  6. ABAP 在被访问的程序中获取访问程序的全局变量

    前些日子接到过一个看起来比较普通的需求: 存在一个系统标准函数组FG01,内含函数模块FM00,FM01……等等.在系统程序中,FM00会调用FM01,通过FM01获取获取某些数据. 需求要求,复制一 ...

  7. web笔试

    类型判断用到哪些方法? typeof和instanceof 值类型和引用类型的区别? 根据 JavaScript中的变量类型传递方式,又分为值类型和引用类型,在参数传递方式上,值类型是按值传递,引用类 ...

  8. 怎么配置 Oracle 侦听器来使用SQL操作ST_Geometry

    关于这个内容,其实从ArcSDE9.2推出ST_Geometry就让用户感到很有吸引力,而且特别是在ArcSDE9.3之后,用户使用SQL操作ST_geometry越来越多,但是在配置Oracle监听 ...

  9. Spark本地运行成功,集群运行空指针异。

    一个很久之前写的Spark作业,当时运行在local模式下.最近又开始处理这方面数据了,就打包提交集群,结果频频空指针.最开始以为是程序中有null调用了,经过排除发现是继承App导致集群运行时候无法 ...

  10. vue学习路由嵌套

    1. 路由嵌套和参数传递 传参的两种形式: a.查询字符串:login?name=tom&pwd=123 {{$route.query}} ------ <li><route ...