大话设计模式之工厂模式 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 != )
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#的更多相关文章
- 负载均衡算法,轮询方式 大话设计模式之工厂模式 C#
负载均衡算法,轮询方式 2018-04-13 17:37 by 天才卧龙, 13 阅读, 0 评论, 收藏, 编辑 学无止境,精益求精 十年河东,十年河西,莫欺少年穷 学历代表你的过去,能力代表你的现 ...
- 大话设计模式--抽象工厂模式 Abstract Factory -- C++实现实例
1. 抽象工厂模式: 提供一个创建一系列相关或者相互依赖对象的接口,而无需指定他们具体的类. 下面是工厂方法模式: 下面是抽象工厂模式: 和工厂方法模式相比 抽象工厂模式可以有多个Product抽象, ...
- C#学习之设计模式:工厂模式
最近研究一下设计模式中工厂模式的应用,在此记录如下: 什么是工厂模式? 工厂模式属于设计模式中的创造型设计模式的一种.它的主要作用是协助我们创建对象,为创建对象提供最佳的方式.减少代码中的耦合程度,方 ...
- linkin大话设计模式--抽象工厂
linkin大话设计模式--抽象工厂 在前面讲到的简单工厂里面虽然实现了我们那个类和其中的依赖的解耦,但是在产生我们需要的依赖的那个工厂里面还是和具体的产品类耦合了 现在要是还想彻底解耦的话怎么办呢 ...
- 设计模式之工厂模式(c++)
问题描述 在面向对象系统设计中经常可以遇到以下的两类问题:1)为了提高内聚(Cohesion)和松耦合(Coupling),我们经常会抽象出一些类的公共接口以形成抽象基类或者接口.这样我们可以通过声明 ...
- C# Json反序列化 C# 实现表单的自动化测试<通过程序控制一个网页> 验证码处理类:UnCodebase.cs + BauDuAi 读取验证码的值(并非好的解决方案) 大话设计模式:原型模式 C# 深浅复制 MemberwiseClone
C# Json反序列化 Json反序列化有两种方式[本人],一种是生成实体的,方便处理大量数据,复杂度稍高,一种是用匿名类写,方便读取数据,较为简单. 使用了Newtonsoft.Json,可以自 ...
- python 设计模式之工厂模式 Factory Pattern (简单工厂模式,工厂方法模式,抽象工厂模式)
十一回了趟老家,十一前工作一大堆忙成了狗,十一回来后又积累了一大堆又 忙成了狗,今天刚好抽了一点空开始写工厂方法模式 我看了<Head First 设计模式>P109--P133 这25页 ...
- 设计模式——抽象工厂模式及java实现
设计模式--抽象工厂模式及java实现 设计模式在大型软件工程中很重要,软件工程中采用了优秀的设计模式有利于代码维护,方便日后更改和添加功能. 设计模式有很多,而且也随着时间在不断增多,其中最著名的是 ...
- 5. 星际争霸之php设计模式--抽象工厂模式
题记==============================================================================本php设计模式专辑来源于博客(jymo ...
随机推荐
- Python 基于Python实现批量创建目录
基于Python实现批量创建目录 by:授客QQ:1033553122 测试环境: Python版本:Python 2.7 代码实践 #!/usr/bin/env python # -*- cod ...
- .NetCore(四) 在Nginx部署
本篇主要体验一下Nginx的使用,之前只接触过IIS. 一.Nginxa) ASP.NET Core内置了Kestrel服务器,但功能简单,主要用于SelfHost,正式运行还是要依赖IIS.Apa ...
- OkHttp封装之后使用
代码都封装好了,上层Activity如何调用呢? 1.依赖 如果是android studio开发支持在线依赖(我已经把项目添加到jcenter上): compile 'com.ansen.http: ...
- [Android] 设置AlertDialog中按钮的可用(Enable)状态
弹出一个保存文件的对话框,要控制输入内容限制,同时内容为空时保存按钮不可用. 原文地址请保留http://www.cnblogs.com/rossoneri/p/4140184.html 直接上代码: ...
- [20171106]修改show spparameter的显示宽度.txt
[20171106]修改show spparameter的显示宽度.txt --//很多年前做的,修改show parameter的显示宽度.--//链接: [20121023]改变show para ...
- 使用linq语句进行联表查询
假设你有一个父表(例如:汽车),其关联一个子表,例如轮子(一对多).现在你想对于所有的父表汽车,遍历所有汽车,然后打印出来所有轮子的信息.默认的做法将是: SELECT CarId FROM Cars ...
- Dos烧录脚本
Dos命令之前更改的太简单,现在加入判断是否进入fasboot模式和判断Android镜像是否存在:代码已经尽量简化成这样,dos命令功能还是比较不好用的,用了一下午的时间... @echo off ...
- 第 16 章 C 预处理器和 C 库(string.h 库中的 memcpy() 和 memmove())
/*----------------------------------------- mems.c -- 使用 memcpy() 和 memmove() ---------------------- ...
- Linux 小知识翻译 - 「版本号」的命名方式
包括OS,所有的软件都有版本号信息.一般来说,版本号的增大表示软件的功能增强了或者修正了一些Bug,也就是表示软件更新了. 版本号的命名方式没有统一的标准.每种软件都不一样. 大部分情况下,版本号以「 ...
- Python3编写网络爬虫08-数据存储方式一-文件存储
数据存储 用解析器解析出数据之后,就是存储数据了.保存的形式可以多种多样,最简单的形式是直接保存为文本文件,如TXT JSON CSV等.另外还可以保存到数据库中,如关系型数据库MySQL 非关系型数 ...