`
jiaguwen123
  • 浏览: 411407 次
  • 性别: Icon_minigender_2
  • 来自: 深圳
社区版块
存档分类
最新评论

设计模式六大原则

阅读更多


 对可维护性的支持:

一、 "开放-封闭"原则(OCP)
Open-Closed Principle原则讲的是:一个软件实体应当对扩展开放,对修改关闭。

优点:
    通过扩展已有软件系统,可以提供新的行为,以满足对软件的新的需求,使变化中的软件有一定的适应性和灵活性。
    已有软件模块,特别是最重要的抽象层模块不能再修改,这使变化中的软件系统有一定的稳定性和延续性。

例子:玉帝招安美猴王
当年大闹天宫便是美猴王对玉帝的新挑战。美猴王说:"'皇帝轮流做,明年到我家。'只教他搬出去,将天宫让于我!"对于这项挑战,太白金星给玉皇大帝提出的建议是:"降一道招安圣旨,宣上界来…,一则不劳师动众,二则收仙有道也。"

换而言之,不劳师动众、不破坏天规便是"闭",收仙有道便是"开"。招安之道便是玉帝天庭的"开放-封闭"原则。

 

 

招安之法的关键便是不允许更改现有的天庭秩序,但允许将妖猴纳入现有秩序中,从而扩展了这一秩序。用面向对象的语言来讲,不允许更改的是系统的抽象层,而允许更改的是系统的实现层。


二、 里氏代换原则(LSP)
Liskov Substitution Principle(里氏代换原则):子类型(subtype)必须能够替换它们的基类型。

白马、黑马
 

 

反过来的代换不成立
《墨子·小取》说:"娣,美人也,爱娣,非爱美人也……"娣便是妹妹,哥哥喜爱妹妹,是因为两人是兄妹关系,而不是因为妹妹是个美人。因此,喜爱妹妹不等同于喜爱美人。用面向对象语言描述,美人是基类,妹妹是美人的子类。哥哥作为一个有"喜爱()"方法,接受妹妹作为参数。那么,这个"喜爱()"方法一般不能接受美人的实例。

 

 

一个违反LSP的简单例子(长方形和正方形)

public class Rectangle
{
   private long width;
   private long height;
   
   public void setWidth(long width)
   {
      this.width = width;
   }
   public long getWidth()
   {
      return this.width;
   }
   public void setHeight(long height)
   {
      this.height = height;
   }
   public long getHeight()
   {
      return this.height;
   }
}

public class Square
{
   private long side;
   
   public void setSide(long side)
   {
      this.side = side;
   }

   public long getSide()
   {
      return side;
   }
}

正方形不可以做长方形的子类

using System;

public class Rectangle
{
   private long width;
   private long height;
   
   public void setWidth(long width)
   {
      this.width = width;
   }
   public long getWidth()
   {
      return this.width;
   }
   public void setHeight(long height)
   {
      this.height = height;
   }
   public long getHeight()
   {
      return this.height;
   }
}

public class Square : Rectangle
{
   private long side;

   public void setWidth(long width)
   {
      setSide(width);
   }

   public long getWidth()
   {
      return getSide();
   }

   public void setHeight(long height)
   {
      setSide(height);
   }

   public long getHeight()
   {
      return getSide();
   }

   public long getSide()
   {
      return side;
   }

   public void setSide(long side)
   {
      this.side = side;
   }
}

public class SmartTest
{
   public void resize(Rectangle r)
   {
      while (r.getHeight() >= r.getWidth() )
      {
         r.setWidth(r.getWidth() + 1);
      }
   }
}
 

 
在执行SmartTest的resize方法时,如果传入的是长方形对象,当高度大于宽度时,会自动增加宽度直到超出高度。但是如果传入的是正方形对象,则会陷入死循环。

代码重构

public interface Quadrangle
{
   public long getWidth();
   public long getHeight();
}

public class Rectangle : Quadrangle
{
   private long width;
   private long height;
   
   public void setWidth(long width)
   {
      this.width = width;
   }
   public long getWidth()
   {
      return this.width;
   }
   public void setHeight(long height)
   {
      this.height = height;
   }
   public long getHeight()
   {
      return this.height;
   }
}

public class Square : Quadrangle
{
   private long side;

   public void setSide(long side)
   {
      this.side = side;
   }

   public long getSide()
   {
      return side;
   }

   public long getWidth()
   {
      return getSide();
   }

   public long getHeight()
   {
      return getSide();
   }
}

 



 三、 依赖倒置原则(DIP)
依赖倒置(Dependence Inversion Principle)原则讲的是:要依赖于抽象,不要依赖于具体。

简单的说,依赖倒置原则要求客户端依赖于抽象耦合。原则表述:

抽象不应当依赖于细节;细节应当依赖于抽象;
要针对接口编程,不针对实现编程。

反面例子:

 

 

缺点:耦合太紧密,Light发生变化将影响ToggleSwitch。

解决办法一:
将Light作成Abstract,然后具体类继承自Light。

 

 

优点:ToggleSwitch依赖于抽象类Light,具有更高的稳定性,而BulbLight与TubeLight继承自Light,可以根据"开放-封闭"原则进行扩展。只要Light不发生变化,BulbLight与TubeLight的变化就不会波及ToggleSwitch。

缺点:如果用ToggleSwitch控制一台电视就很困难了。总不能让TV继承自Light吧。

解决方法二:
 

 

优点:更为通用、更为稳定。

结论:
使用传统过程化程序设计所创建的依赖关系,策略依赖于细节,这是糟糕的,因为策略受到细节改变的影响。依赖倒置原则使细节和策略都依赖于抽象,抽象的稳定性决定了系统的稳定性。

四、 接口隔离原则(ISP)
接口隔离原则(Interface Segregation Principle)讲的是:使用多个专门的接口比使用单一的总接口总要好。换而言之,从一个客户类的角度来讲:一个类对另外一个类的依赖性应当是建立在最小接口上的。

过于臃肿的接口是对接口的污染。不应该强迫客户依赖于它们不用的方法。

My object-oriented umbrella(摘自Design Patterns Explained)

Let me tell you about my great umbrella. It is largeenough to get into! In fact, three or four other people can get in itwith me. While we are in it, staying out of the rain, I can move itfrom one place to another. It has a stereo system to keep meentertained while I stay dry. Amazingly enough, it can also conditionthe air to make it warmer or colder. It is one cool umbrella.

My umbrella is convenient. It sits there waiting forme. It has wheels on it so that I do not have to carry it around. Idon't even have to push it because it can propel itself. Sometimes, Iwill open the top of my umbrella to let in the sun. (Why I am using myumbrella when it is sunny outside is beyond me!)

In Seattle, there are hundreds of thousands of these umbrellas in all kinds of colors. Most people call them cars.

实现方法:
1、 使用委托分离接口
2、 使用多重继承分离接口

五、 合成/聚合复用原则(CARP)
合成/聚合复用原则(Composite/Aggregate ReusePrinciple或CARP)经常又叫做合成复用原则(Composite ReusePrinciple或CRP),就是在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分;新对象通过向这些对象的委派达到复用已有功能的目的。

简而言之,要尽量使用合成/聚合,尽量不要使用继承。

o Design to interfaces.
o Favor composition over inheritance.
o Find what varies and encapsulate it.
(摘自:Design Patterns Explained)

区分"Has-A"与"Is-A"

"Is-A"是严格的分类学意义上定义,意思是一个类是另一个类的"一种"。而"Has-A"则不同,它表示某一个角色具有某一项责任。

导致错误的使用继承而不是合成/聚合的一个常见的原因是错误的把"Has-A"当作"Is-A"。

例如:
 

 

实际上,雇员、经理、学生描述的是一种角色,比如一个人是"经理"必然是"雇员",另外一个人可能是"学生雇员",在上面的设计中,一个人无法同时拥有多个角色,是"雇员"就不能再是"学生"了,这显然是不合理的。

错误源于把"角色"的等级结构与"人"的等级结构混淆起来,误把"Has-A"当作"Is-A"。解决办法:

 

 

六、 迪米特法则(LoD)
迪米特法则(Law of Demeter或简写LoD)又叫最少知识原则(Least Knowledge Principle或简写为LKP),也就是说,一个对象应当对其它对象有尽可能少的了解。

其它表述:
  只与你直接的朋友们通信
  不要跟"陌生人"说话
  每一个软件单位对其它的单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位。

迪米特法则与设计模式
Facade模式、Mediator模式

使民无知
《老子》第三章曰:"是以圣人之治,虚其心,实其腹,弱其志,常使民无知无欲。"使被"统治"的对象"愚昧"化,处于"无知"的状态,可以使"统治"的成本降低。
所谓"最少知识"原则,实际上便是老子的"使民无知"的统治之术。

不相往来
《老子》云:"小国寡民……邻国相望,鸡犬之声相闻,民至老死,不相往来。"将被统治的对象隔离开来,使它们没有直接的通信,可以达到分化瓦解,继而分而治之的效果。迪米特法则与老子的"小国寡民"的统治之术不谋而合。


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/WuOu/archive/2008/03/03/2142370.aspx

  • 大小: 3.6 KB
  • 大小: 2.2 KB
  • 大小: 1.7 KB
  • 大小: 8.1 KB
  • 大小: 9.6 KB
  • 大小: 1.6 KB
  • 大小: 2.8 KB
  • 大小: 5.2 KB
  • 大小: 1.8 KB
  • 大小: 2.3 KB
分享到:
评论

相关推荐

    设计模式六大原则与类的六种关系

    设计模式六大原则与类的六种关系 设计模式六大原则是软件设计中遵循的一些基本原则,目的是为了使软件设计更加灵活、可维护和可扩展。六大原则分别是:单一职责原则、里氏替换原则、依赖倒置原则、接口隔离原则、...

    php 设计模式六大原则

    php 设计模式六大原则 单一职责原则 里氏替换原则 依赖倒置原则 接口隔离原则 迪米特法则 开闭原则 word版

    设计模式之六大原则详解,Markdown笔记

    详细介绍了设计模式六大原则,配有示例代码和图片,有开闭原则,单一职责原则,里氏替换原则,依赖倒置原则,接口隔离原则,迪米特法则等等。

    设计模式六大原则.doc

    设计模式六大原则是软件开发中不可或缺的指导方针,它们旨在提升代码的可维护性、可扩展性和可重用性。以下是对这些原则的详细解释: 1. 单一职责原则(Single Responsibility Principle, SRP): 这个原则强调一个...

    23种设计模式和设计模式六大原则

    文档为23种设计模式中的15种设计模式和设计模式六大原则,里面写的某种模式的优缺点,适用场景,具体代码,注意事项,典型应用。具体写的挺好,希望能帮助你。

    设计模式六大原则详解 经典

    在这篇文章中,我们将深入探讨设计模式的六大原则,这些原则是理解并有效应用设计模式的基础。 首先,我们要了解“开-闭”原则(Open-Closed Principle,OCP)。这个原则指出,一个软件实体(如类、模块或函数)...

    设计模式六大原则 .docx

    设计模式六大原则是软件开发中不可或缺的指导原则,它们旨在提高代码的可维护性、可扩展性和可重用性。以下是对这六个原则的详细解释: 1、单一职责原则(SRP) 单一职责原则指出,一个类或模块应只负责一项功能。...

    设计模式六大原则(1):单一职责原则

    设计模式六大原则是面向对象编程中的基石,为代码的可维护性、扩展性和复用性提供了指导。本文将深入探讨这六大原则中的第一个——单一职责原则(Single Responsibility Principle, SRP),并结合AcountYear.java这...

    JAVA设计模式六大原则详细讲解(面向对象语言通用)

    1.单一职责原则: 不要存在多于一个导致类变更的原因 ...接口隔离原则告诉我们在设计接口的时候要精简单一;迪米特法则告诉我们要降低耦合。而开闭原则是总纲,他告诉我们要对扩展开放,对修改关闭。

    设计模式6大原则.zip

    在这个案例中,它可能提到了如何阅读和理解《Spring源码深度解析.pdf》中的内容,或者对设计模式六大原则的进一步说明和应用指导。 总之,设计模式六大原则是软件设计的核心思想,它们为构建高质量、可维护的软件...

    Beatles9527#StudyNotes#_1设计模式六大原则1

    1. 单一职责原则 2. 依赖倒置原则 3. 迪米特法则 4. 开放-封闭原则 5. 里氏替换原则(了解) 6. 接口隔离原则(了解)

Global site tag (gtag.js) - Google Analytics