前言:毫无疑问 ,学习一些设计模式,对我们的编程水平的提高帮助很大。写这个博客的时候自己刚开始学习设计模式,难免有错,欢迎评论指正。

我学设计模式的第一本书是“大话设计模式”。

1.为什么要学设计模式?

设计模式的存在就是为了抵御需求变更。学会了这些思想,开始一个项目的时候考虑的更多,当用户提出变更的时候项目改动更少。

2.怎么才能学会设计模式?

我不知道,不过轮子哥(vczh)文章中的一句话,我觉得对,就是:“设计模式就是因为情况复杂了所以才会出现的,所以我们只能通过复杂的程序来学习设计模式。你不管看别人的程序也好,自己写程序练习也好,那必须要复杂,复杂到你不用设计模式就做不下去,这才能起到学习设计模式的作用”。所以,我准备选择一些自己用到的设计模式,通过写代码的方式去熟悉它们。

一.简单工厂模式(Simple Factory Pattern)

场景描述:制作一个计算器。

1.实现加减乘除。

2.以后有其它算法的时候,容易维护。

工厂类

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//Author:cuishiyu
//2016.08.13
namespace OperationByFactory.Class
{
//运算工厂类
class OperationFactory
{
public static Operation createOperation(string operate)
{
Operation oper = null;
switch (operate)
{
case "+":
oper = new OperationAdd();
break;
case "-":
oper = new OperationSub();
break;
case "*":
oper = new OperationMul();
break;
case "/":
oper = new OperationDiv();
break;
}
return oper;
}
}
}

运算类

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//Author:cuishiyu
//2016.08.13
namespace OperationByFactory.Class
{
//运算类
class Operation
{
private double _numberA = ;
private double _numberB = ; public double NumberA
{
get
{
return _numberA;
} set
{
_numberA = value;
}
} public double NumberB
{
get
{
return _numberB;
} set
{
_numberB = value;
}
} public virtual double GetResult()
{
double result = ;
return result;
}
}
}

加减乘除类

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//Author:cuishiyu
//2016.08.13
namespace OperationByFactory.Class
{
//加法类
class OperationAdd:Operation
{
public override double GetResult()
{
return NumberA + NumberB;
}
}
}
 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//Author:cuishiyu
//2016.08.13
namespace OperationByFactory.Class
{
//减法类
class OperationSub:Operation
{
public override double GetResult()
{
return NumberA - NumberB;
}
}
}
 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//Author:cuishiyu
//2016.08.13
namespace OperationByFactory.Class
{
//乘法类
class OperationMul:Operation
{
public override double GetResult()
{
return NumberA * NumberB;
}
}
}
 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//Author:cuishiyu
//2016.08.13
namespace OperationByFactory.Class
{
//除法类
class OperationDiv:Operation
{
public override double GetResult()
{
if(NumberB== )
throw new Exception("除数不能为0");
return NumberA / NumberB;
}
}
}

总结:简单工厂模式很简单,重要的是。这个设计模式是怎么一步步形成的、和这样做的好处有哪些。

1.可移植性号,无论是控制台程序,Windows程序,Web程序,都可以用这段代码。

2.扩展性好,更安全,以后增加平方,立方,开根号等运算的时候,增加一个相应的类,然后再Switch里增加分支就好了。同时也不用担心程序员修改原先写好的加减乘除类,使得原先的代码不会被有意或者无意的修改,所以更安全。

3.(1)编程尽可能避免重复的代码。(2)对业务进行封装,尽可能的让业务逻辑和页面逻辑分开,让它们的耦合度下降,这样更容易维护和扩展。

4.大家可以熟悉一下UML类图,画出来之后理解更直观。

二.策略模式(strategy Pattern

场景描述:商场的收银软件,收银员根据客户所购买的商品单价和数量进行收费。

1.要考虑到打折的情况(比如过节打8折)。

2.要考虑满A返B的情况(比如满300返100)。

3.考虑以后发生其它情况是,尽量做到代码容易更改,安全的更改。

注:部分代码是伪代码

抽象策略类

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace PromotionByStrategy
{
//抽象策略类
abstract class CashSuper
{
public abstract double acceptCatch(double money);
}
}

返利收费子类

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace PromotionByStrategy
{
//返利收费子类
class CashReturn : CashSuper
{
private double moneyCondition = 0.0d;
private double moneyReturn = 0.0d;
public CashReturn(string moneyCondition, string moneyReturn)
{
this.moneyCondition = double.Parse(moneyCondition);
this.moneyReturn = double.Parse(moneyReturn);
}
public override double acceptCatch(double money)
{
double result = money;
if (money >= moneyCondition)
{
result = money - Math.Floor(money / moneyCondition) * moneyReturn;
}
return result;
}
}
}

打折收费子类

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace PromotionByStrategy
{
//打折收费子类
class CashRebate : CashSuper
{
private double moneyRebate = 1d; //构造函数传入打折信息
public CashRebate(string moneyRebate)
{
this.moneyRebate = double.Parse(moneyRebate);
} public override double acceptCatch(double money)
{
return money * moneyRebate;
}
}
}

正常收费子类

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace PromotionByStrategy
{
//正常收费子类
class CashNormal : CashSuper
{
public override double acceptCatch(double money)
{
return money;
}
}
}

策略和简单工厂的结合

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace PromotionByStrategy
{
//策略和简单工厂的结合
class CashContext
{
//收钱的父类
CashSuper cs = null; /// <summary>
/// 构造函数初始化收费类型对象
/// </summary>
/// <param name="type"></param>
public CashContext(string type)//传入一个收费的类型
{
switch (type)//根据不同的类型实例化不同的收款算法对象
{
case"正常收费":
cs = new CashNormal();
break;
case "满A减B":
cs = new CashReturn("A", "B");
break;
case "打X折":
cs = new CashRebate("0.X");
break;
}
} public double GetResult(double money)
{
return cs.acceptCatch(money);
}
}
}

客户端的主要程序

  double tatal = 0.0d;
//客户端的主要程序
//传入算法,和价格*数量,得到应收的钱
public void btnOK_Click()
{
CashContext csuper = new CashContext("传入收款的算法");
double totalPrices = 0.0d;
totalPrices = csuper.GetResult(Convert.ToDouble("价格*数量"));
}

总结:在分析一个项目中,遇到不同的时间应用不同的业务规则,就可以考虑使用策略模式处理这种变化的可能性。这个代码还可以优化,后面会用反射进行优化

三.单一职责原则(SRP)

注:三、四、五主要分享设计模式中用到的一些原则

就一个类而言,因该仅有一个引起它变化的原因。一个类只行使一个功能,后面维护的时候会方便许多。

四.开放-封闭原则(The Open-Closeed Principle)

对软件实体来说(类、模块。函数)都要求满足:

两大特征:对扩张是开放的(Open for extension),对更改是封闭的(Closed for modification)。

在具体的实现过程中,可按照下面做:

1.我们在最初编码的时候,假设变化不会发生。当发生变化的时候,我们就创建抽象来隔离以后发生的同类变化。

2.当面对需求的时候,对程序的改动,是通过增加代码而不是修改现有的代码实现。

3.拒绝不成熟的抽象,和抽象本身同样重要。

五.依赖倒转原则

1.依赖倒转原则:抽象不应该依赖细节,细节应该依赖抽象。

简单解释就是,针对接口编程而不是针对实现编程。

A.高模块不应该依赖低层模块。两个都应该依赖抽象。

B.抽象不应该依赖细节,细节应该依赖抽象。

2.里氏代换原则:子类型必须能够替换掉他们的父类型。

简单解释就是,一个软件实体如果使用的是一个父类的话,那么一定使用于其子类,而且它察觉不出父类对象和子类对象的区别。

也就是说,在软件里面,把父类都替换成它的子类,程序行为没有变化。

 六.装饰模式

场景描述:写一个给人搭配不同服饰的系统,类似QQ秀,或者游戏皮肤之类的。

Person类

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace DressByDecorator
{
//Person类
class Person
{
public Person()
{ } private string name; public Person(string name)
{
this.name = name;
} public virtual void Show()
{
Console.WriteLine("装扮的{0}",name);
}
}
}

服饰类,继承Person类

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace DressByDecorator
{
//服饰类
class Finery : Person
{
protected Person componnet; //打扮
public void Decorate(Person component)
{
this.componnet = component;
} public override void Show()
{
if (componnet != null)
{
componnet.Show();
}
}
}
}

具体的服饰类,下面举两个例子。

鞋子类,继承服饰类。

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace DressByDecorator
{
//鞋子类
class Shose:Finery
{
public override void Show()
{
Console.WriteLine("鞋子");
base.Show();
}
}
}

T恤类,继承服饰类。

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace DressByDecorator
{
//T恤类
class TShirts:Finery
{
public override void Show()
{
Console.WriteLine("T恤");
base.Show();
}
}
}

下面是main函数里的实现

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace DressByDecorator
{
//Person类
class Person
{
public Person()
{ } private string name; public Person(string name)
{
this.name = name;
} public virtual void Show()
{
Console.WriteLine("装扮的{0}",name);
}
}
}

装饰模式(Decorator),动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更加灵活。

总结:这个例子中,每一个类都形式自己的功能。他们公有的功能都写在了父类。可以实现动态的添加更多的衣服。

最新文章

  1. Android四大组件知识整理
  2. [No00000C]Word快捷键大全 Word2013/2010/2007/2003常用快捷键大全
  3. Podfile升级后的影响
  4. JAVASE02-Unit01: API文档 、 字符串基本操作
  5. [C#] 编程控制笔记本蓝牙与外部蓝牙设备通信
  6. SqlMapConfig.xml中的setting属性设置
  7. mysql 权限控制
  8. 域名的MX设置及校验方法
  9. HTML5拖拽功能drag
  10. 一步步学习ASP.NET MVC3 (4)——Razor(2)
  11. 了解JavaScript的执行上下文
  12. 构建工具Gradle安装和简单使用
  13. MySql5.6性能优化
  14. Win下安装MySQL 5.6
  15. linux:终端常用命令 + vi命令修改文件及保存 方法
  16. bzoj千题计划322:bzoj2561: 最小生成树(最小割)
  17. Html5与Css3知识点拾遗(五)
  18. [引]ionic framework 相关网站
  19. CentOS 7 安装SVN服务端
  20. spark 数据读取与保存

热门文章

  1. Delphi第三方控件安装方式
  2. Delphi:校验手机号及身份证号
  3. Redis的集群方案之Sentinel(哨兵模式)(待实践)
  4. 踩坑录-利用Apche-POI.XSSFWorkbook.write,处理excel文件,通过response.outputstram下载文件,预览乱码。
  5. REST API 安全设计
  6. POJ2155 Matrix 【二维树状数组】+【段更新点查询】
  7. c# GDI+绘制不同字体的字符串
  8. 通过shell脚本批处理es数据
  9. Swing手动进行最大化最小化
  10. Web 设计与开发者必须知道的 15 个站点