c#版本23个设计模式
最近把设计模式完整看了⼀遍~
看完感觉,要再多看即便,并且写代码的时候要想着能不能⽤设计模式~
经过这段时间对设计模式的学习,⾃⼰的感触还是很多的,因为我现在在写代码的时候,经常会想想这⾥能不能⽤什么设计模式来进⾏重构。所以,学完设计模式之后,感觉它会慢慢地影响到你写代码的思维⽅式。这⾥对设计模式做⼀个总结,⼀来可以对所有设计模式进⾏⼀个梳理,⼆来可以做⼀个索引来帮助⼤家收藏。
  PS: 其实,很早之前我就看过所有的设计模式了,但是并没有写博客,但是不久就很快忘记了,也没有起到什么作⽤,这次以博客的形式总结出来,发现效果还是很明显的,因为通过这种总结的⽅式,我对它理解更深刻了,也记住的更牢靠了,也影响了⾃⼰平时实现功能的思维。所以,我⿎励⼤家可以通过做笔记的⽅式来把⾃⼰学到的东西进⾏梳理,这样相信可以理解更深,更好,我也会⼀直写下来,之后打算写WCF⼀系列⽂章。
  其实WCF内容很早也看过了,并且博客园也有很多前辈写的很好,但是,我觉得我还是需要⾃⼰总结,因为只有这样,知识才是⾃⼰的,别⼈写的多好,你看了之后,其实还是别⼈了,所以⿎励⼤家⼏点(对于这⼏点,也是对⾃⼰的⼀个提醒):
1. 要动⼿实战别⼈博客中的例⼦;
2. 实现之后进⾏总结,可以写博客也可以⾃⼰记录云笔记等;
3. 想想能不能进⾏扩展,进⾏举⼀反三。
  系列导航:
⼆、设计原则
  使⽤设计模式的根本原因是适应变化,提⾼代码复⽤率,使软件更具有可维护性和可扩展性。并且,在进⾏设计的时候,也需要遵循以下⼏个原则:单⼀职责原则、开放封闭原则、⾥⽒代替原则、依赖倒置原则、接⼝隔离原则、合成复⽤原则和迪⽶特法则。下⾯就分别介绍了每种设计原则。
2.1 单⼀职责原则
  就⼀个类⽽⾔,应该只有⼀个引起它变化的原因。如果⼀个类承担的职责过多,就等于把这些职责耦合在⼀起,⼀个职责的变化可能会影响到其他的职责,另外,把多个职责耦合在⼀起,也会影响复⽤性。
2.2 开闭原则(Open-Closed Principle)
  开闭原则即OCP(Open-Closed Principle缩写)原则,该原则强调的是:⼀个软件实体(指的类、函数、模块等)应该对扩展开放,对修改关闭。即每次发⽣变化时,要通过添加新的代码来增强现有类型的⾏为,⽽不是修改原有的代码。
  符合开闭原则的最好⽅式是提供⼀个固有的接⼝,然后让所有可能发⽣变化的类实现该接⼝,让固定的接⼝与相关对象进⾏交互。
2.3 ⾥⽒代替原则(Liskov Substitution Principle)
  Liskov Substitution Principle,LSP(⾥⽒代替原则)指的是⼦类必须替换掉它们的⽗类型。也就是说,在软件开发过程中,⼦类替换⽗类后,程序的⾏为是⼀样的。只有当⼦类替换掉⽗类后,此时软件的功能不受影响时,⽗类才能真正地被复⽤,⽽⼦类也可以在⽗类的基础上添加新的⾏为。为了就来看看违反了LSP原则的例⼦,具体代码如下所⽰:
public class Rectangle
{
public virtual long Width { get; set; }
public virtual long Height { get; set; }
}
// 正⽅形
public class Square : Rectangle
{
public override long Height
{
get
{
return base.Height;
}
set
{
base.Height = value;
base.Width = value;
}
}
public override long Width
{
get
{
return base.Width;
}
set
{
base.Width = value;
base.Height = value;
}
}
}
class Test
{
public void Resize(Rectangle r)
{
单例模式的几种实现方式
while (r.Height >= r.Width)
{
r.Width += 1;
}
}
var r = new Square() { Width = 10, Height = 10 };
new Test().Resize(r);
}
  上⾯的设计,正如上⾯注释的⼀样,在执⾏SmartTest的resize⽅法时,如果传⼊的是长⽅形对象,当⾼度⼤于宽度时,会⾃动增加宽度直到超出⾼度。但是如果传⼊的是正⽅形对象,则会陷⼊死循环。此时根本原因是,矩形不能作为正⽅形的⽗类,既然出现了问题,可以进⾏重构,使它们俩都继承于四边形类。重构后的代码如下所⽰:
/
/ 四边形
public abstract class Quadrangle
{
public virtual long Width { get; set; }
public virtual long Height { get; set; }
}
// 矩形
public class Rectangle : Quadrangle
{
public override long Height { get; set; }
public override long Width { get; set; }
}
// 正⽅形
public class Square : Quadrangle
{
public long _side;
public Square(long side)
{
_side = side;
}
}
class Test
{
public void Resize(Quadrangle r)
{
while (r.Height >= r.Width)
{
r.Width += 1;
}
}
static void Main(string[] args)
{
var s = new Square(10);
new Test().Resize(s);
}
}
2.4 依赖倒置原则
  依赖倒置(Dependence Inversion Principle, DIP)原则指的是抽象不应该依赖于细节,细节应该依赖于抽象,也就是提出的 “⾯向接⼝编程,⽽不是⾯向实现编程”。这样可以降低客户与具体实现的耦合。
2.5 接⼝隔离原则
  接⼝隔离原则(Interface Segregation Principle, ISP)指的是使⽤多个专门的接⼝⽐使⽤单⼀的总接⼝要好。也就是说不要让⼀个单⼀的接⼝承担过多的职责,⽽应把每个职责分离到多个专门的接⼝中,进⾏接⼝分离。过于臃肿的接⼝是对接⼝的⼀种污染。
2.6 合成复⽤原则
  合成复⽤原则(Composite Reuse Principle, CRP)就是在⼀个新的对象⾥⾯使⽤⼀些已有的对象,使之成为新对象的⼀部分。新对象通过向这些对象的委派达到复⽤已⽤功能的⽬的。简单地说,就是要尽量使⽤合成/聚合,尽量不要使⽤继承。
  要使⽤好合成复⽤原则,⾸先需要区分"Has—A"和“Is—A”的关系。
  “Is—A”是指⼀个类是另⼀个类的“⼀种”,是属于的关系,⽽“Has—A”则不同,它表⽰某⼀个⾓⾊具有某⼀项责任。导致错误的使⽤继承⽽不是聚合的常见的原因是错误地把“Has—A”当成“Is—A”.例如:
实际上,雇员、经历、学⽣描述的是⼀种⾓⾊,⽐如⼀个⼈是“经理”必然是“雇员”。在上⾯的设计中,⼀个⼈⽆法同时拥有多个⾓⾊,是“雇员”就不能再是“学⽣”了,这显然不合理,因为现在很多在职研究⽣,即使雇员也是学⽣。
  上⾯的设计的错误源于把“⾓⾊”的等级结构与“⼈”的等级结构混淆起来了,误把“Has—A”当作"Is—A"。具体的解决⽅法就是抽象出⼀个⾓⾊类:
2.7 迪⽶特法则
  迪⽶特法则(Law of Demeter,LoD)⼜叫最少知识原则(Least Knowledge Principle,LKP),指的是⼀个对象应当对其他对象有尽可能少的了解。也就是说,⼀个模块或对象应尽量少的与其他实体之间发⽣相互作⽤,使得系统功能模块相对独⽴,这样当⼀个模块修改时,影响的模块就会越少,扩展起来更加容易。
  关于迪⽶特法则其他的⼀些表述有:只与你直接的朋友们通信;不要跟“陌⽣⼈”说话。
  外观模式(Facade Pattern)和中介者模式(Mediator Pattern)就使⽤了迪⽶特法则。
三、创建型模式
  创建型模式就是⽤来创建对象的模式,抽象了实例化的过程。所有的创建型模式都有两个共同点。第⼀,它们都将系统使⽤哪些具体类的信息封装起来;第⼆,它们隐藏了这些类的实例是如何被创建和
组织的。创建型模式包括单例模式、⼯⼚⽅法模式、抽象⼯⼚模式、建造者模式和原型模式。
单例模式:解决的是实例化对象的个数的问题,⽐如抽象⼯⼚中的⼯⼚、对象池等,除了Singleton之外,其他创建型模式解决的都是 n ew 所带来的耦合关系。
抽象⼯⼚:创建⼀系列相互依赖对象,并能在运⾏时改变系列。
⼯⼚⽅法:创建单个对象,在Abstract Factory有使⽤到。
原型模式:通过拷贝原型来创建新的对象。
  ⼯⼚⽅法,抽象⼯⼚, 建造者都需要⼀个额外的⼯⼚类来负责实例化“⼀个对象”,⽽Prototype则是通过原型(⼀个特殊的⼯⼚类)来克隆“易变对象”。
  下⾯详细介绍下它们。
3.1  单例模式
  单例模式指的是确保某⼀个类只有⼀个实例,并提供⼀个全局访问点。解决的是实体对象个数的问题,⽽其他的建造者模式都是解决new所带来的耦合关系问题。其实现要点有:
类只有⼀个实例。问:如何保证呢?答:通过私有构造函数来保证类外部不能对类进⾏实例化
提供⼀个全局的访问点。问:如何实现呢?答:创建⼀个返回该类对象的静态⽅法
  单例模式的结构图如下所⽰:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。