设计模式系列(1) 设计模式的五大设计原则
这里我总结了设计模式的五个设计原则,当然,实际可能不止这五种,但是这里总结的是最常见,也是最常用的五种设计原则。设计原则是我们软件设计的目标,设计模式是是我们的具体做法。
一,单一职责原则(SRP):
1,SRP(Single Responsibilities Principle)的定义:就一个类而言,应该仅有一个引起它变化的原因。简而言之,就是功能要单一。
2,如果一个类承担的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会削弱或者抑制这个类完成其它职责的能力。这种耦合会导致脆弱的设计,当变化发生时,设计会遭受到意想不到的破坏。(敏捷软件开发)
3,软件设计真正要做的许多内容,就是发现职责并把那些职责相互分离。(敏捷软件开发)
二,开放-封闭原则(OCP):
1,OCP(Open-Close Principle)的定义:就是说软件实体(类,方法等等)应该可以扩展,但是不能修改。它是软件设计中也是最重要的一种设计原则。
2,OCP的两个特征:
1> 对于扩展是开放的。
2> 对于修改是封闭的。
3,什么时候应用OCP原则呢?
在我们最初编写代码时,假设变化不会发生,当变化发生时,我们就创建抽象(比如抽象类,接口等等)来隔离以后发生的同类变化。
4,开放-封闭原则是面向对象设计的核心所在。遵循这个原则可以带来面向对象技术所声称的巨大好处,也就是可维护,可扩展,可复用,灵活性好。开发人员应该仅对程序中呈现出频繁变化的那些部分做出抽象,然而,对于应用程序中的每个部分都刻意地进行抽象同样不是一个好主意。拒绝不成熟的抽象和抽象本身一样重要。
5,OCP的UML图:
三,依赖倒转原则(DIP):
1,DIP(Dependence Inversion Principle)的定义:抽象不应该依赖细节,细节应该依赖于抽象。简单说就是,我们要针对接口编程,而不要针对实现编程。
反面例子UML图:
缺点:高层模块太依赖低层模块,耦合太紧密。低层模块发生变化会影响到高层模块。
解决方法:利用依赖倒置原则使高层模块和低层模块都依赖于抽象(接口或抽象类)。
修改后的UML图如下:
优点:这样的话修改低层模块不会影响到高层模块,减小了它们之间的耦合度,增强系统的稳定性。
总结:依赖倒置原则其实可以说是面向对象设计的标志,用哪种语言来编写程序不重要,如果编写时考虑的都是如何针对抽象编程而不是针对细节编程,即程序中所有的依赖关系都是终止于抽象类或者接口,那就是面向对象的设计,反之那就是过程化的设计了。
四,里氏替换原则(LSP):
1,LSP(Liskov Substitution Principle)的定义:子类型必须能够替换掉它们的父类型。简单地说,这是因为子类型继承了父类,所以子类可以以父类的身份出现。
实例UML图:
实现的C#代码:
public class Animal { public void Eat() { } public void Drink() { } public void Run() { } public void Shout() { } } public class Cat : Animal { } public class Dog : Animal { } public class Cattle : Animal { } public class Sheep : Animal { }
class Program { static void Main(string[] args) { Animal animal = new Cat();//根据需求的变化,这里可以替换成Dog,Cattle或Sheep,程序其它地方不需要改变 animal.Eat(); animal.Drink(); animal.Run(); animal.Shout(); } }
总结:也正是因为有了里氏替换原则,使得继承复用成为了可能。只有当子类可以替换掉父类,软件单位的功能不受到影响时,父类才能真正被复用,而子类也能够在父类的基础上增加新的行为。
五,迪米特法则(LoD):
1,LoD(Law of Demeter)的定义:如果两个类不必彼此直接通信,那么这两个类就不应当直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。
在类的结构设计上,每一个类都应当尽量降低成员的访问权限,也就是说,一个类包装好自己的private状态,不需要让别的类知道的字段或行为(方法)就尽量不要公开。
TAG: