`
googlelc
  • 浏览: 56524 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

软件设计原则

 
阅读更多

一、 "开放-封闭"原则(OCP)

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

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

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

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

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


二、 里氏代换原则(LSP

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

白马、黑马

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

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

publicclassRectangle
{
privatelongwidth;
privatelongheight;

publicvoidsetWidth(longwidth)
{
this.width=width;
}
publiclonggetWidth()
{
returnthis.width;
}
publicvoidsetHeight(longheight)
{
this.height=height;
}
publiclonggetHeight()
{
returnthis.height;
}
}

publicclassSquare
{
privatelongside;

publicvoidsetSide(longside)
{
this.side=side;
}

publiclonggetSide()
{
returnside;
}
}


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

usingSystem;

publicclassRectangle
{
privatelongwidth;
privatelongheight;

publicvoidsetWidth(longwidth)
{
this.width=width;
}
publiclonggetWidth()
{
returnthis.width;
}
publicvoidsetHeight(longheight)
{
this.height=height;
}
publiclonggetHeight()
{
returnthis.height;
}
}

publicclassSquare:Rectangle
{
privatelongside;

publicvoidsetWidth(longwidth)
{
setSide(width);
}

publiclonggetWidth()
{
returngetSide();
}

publicvoidsetHeight(longheight)
{
setSide(height);
}

publiclonggetHeight()
{
returngetSide();
}

publiclonggetSide()
{
returnside;
}

publicvoidsetSide(longside)
{
this.side=side;
}
}

publicclassSmartTest
{
publicvoidresize(Rectangler)
{
while(r.getHeight()>=r.getWidth())
{
r.setWidth(r.getWidth()+1);
}
}
}


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

代码重构

publicinterfaceQuadrangle
{
publiclonggetWidth();
publiclonggetHeight();
}

publicclassRectangle:Quadrangle
{
privatelongwidth;
privatelongheight;

publicvoidsetWidth(longwidth)
{
this.width=width;
}
publiclonggetWidth()
{
returnthis.width;
}
publicvoidsetHeight(longheight)
{
this.height=height;
}
publiclonggetHeight()
{
returnthis.height;
}
}

publicclassSquare:Quadrangle
{
privatelongside;

publicvoidsetSide(longside)
{
this.side=side;
}

publiclonggetSide()
{
returnside;
}

publiclonggetWidth()
{
returngetSide();
}

publiclonggetHeight()
{
returngetSide();
}
}


三、依赖倒置原则(DIP)

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

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

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

反面例子:



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

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

优点:ToggleSwitch依赖于抽象类Light,具有更高的稳定性,而BulbLightTubeLight继承自Light,可以根 据"开放-封闭"原则进行扩展。只要Light不发生变化,BulbLightTubeLight的变化就不会波及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 large enough to get into! In fact, three or four other people can get in it with me. While we are in it, staying out of the rain, I can move it from one place to another. It has a stereo system to keep me entertained while I stay dry. Amazingly enough, it can also condition the air to make it warmer or colder. It is one cool umbrella.

My umbrella is convenient. It sits there waiting for me. It has wheels on it so that I do not have to carry it around. I don't even have to push it because it can propel itself. Sometimes, I will open the top of my umbrella to let in the sun. (Why I am using my umbrella 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 Reuse PrincipleCARP)经常又叫做合成复用原则(Composite Reuse PrincipleCRP),就是在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分;新对象通过向这些对象的委派达到复用已有功能的目的。

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

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模式

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

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

分享到:
评论

相关推荐

    软件设计原则与实践

    总结来说,软件设计原则在嵌入式领域的应用,要求开发者在设计和实现时考虑系统的可维护性、可扩展性和复用性。通过合理应用开闭原则、单一职责原则、模块化、依赖倒置原则、设计模式以及代码结构的继承和抽象,可以...

    一些软件设计的原则一些软件设计的原则

    【软件设计原则详解】 在软件开发领域,遵循一系列设计原则对于构建高质量、可维护和易于扩展的系统至关重要。以下是一些关键的软件设计原则,它们不仅适用于编程,还能应用于更广泛的生产活动和生活。 1. **Don’...

    软件设计原则-面向对象设计七大原则.zip

    软件设计原则-面向对象设计七大原则.zip 面向对象和C语言完全不是一种思考问题的方式,面向对象是种哲学思想,只有明白了其核心思想,才能以不变应万变 只有吃透面向对象的七大设计原则,比如:依赖倒置原则,迪米特法则等...

    设计模式——6大软件设计原则(demo案例实现,附带解析,快速掌握软件设计原则的精髓)

    该包下的所有demo都是一个个的软件设计原则的案例实现 包含有: 1、开闭原则 2、里氏代换原则 3、依赖倒转原则 4、接口隔离原则 5、迪米特法则 6、合成复用原则 使用了一个个的demo案例,以通俗易懂的生活...

    软件工程中的软件设计原则与设计模式.pptx

    ### 软件工程中的软件设计原则与设计模式 #### 第一章:软件设计原则与设计模式简介 **软件设计原则介绍** 软件设计原则是指在软件开发过程中遵循的一系列基本规则和准则,这些原则旨在帮助开发者设计出结构良好...

    软件工程中的软件设计原则与模式教程1.pptx

    ### 软件工程中的软件设计原则与模式 #### 第一章:软件设计原则的重要性 在软件工程领域,软件设计原则对于构建高质量、高效率的软件系统至关重要。本章节将重点介绍软件设计原则的重要意义,并深入探讨几种核心...

    02-软件设计原则 模式深度解析和案例分析

    ### 软件设计原则与模式深度解析及案例分析 #### 一、软件设计原则的重要性与深度解析 软件设计原则是构建高质量软件的基础。遵循良好的设计原则可以帮助开发者编写出易于维护、扩展性强、且具有良好性能的软件...

    软件设计原则.pptx

    软件设计原则是软件开发中的核心指导思想,它们旨在提高代码的可读性、可维护性和可扩展性。在本文中,我们将深入探讨这六大设计原则,包括它们的定义、应用场景以及如何通过遵循这些原则来优化软件开发过程。 首先...

    软件工程中的软件设计原则与模式.pptx

    ### 软件工程中的软件设计原则与模式 #### 第1章 软件设计原则与模式概述 **软件设计原则介绍** 软件设计原则是指在软件开发过程中为提高软件的质量和可维护性而遵循的一系列设计准则。这些原则主要包括: 1. **...

    软件工程中的软件设计原则与模式教程.pptx

    ### 软件工程中的软件设计原则与模式教程 #### 第1章 软件设计原则的重要性 在软件工程领域,软件设计原则是构建高质量软件系统的基础。这些原则旨在指导开发者设计出健壮、可维护且易于扩展的系统。本章节重点...

    软件工程中的软件设计原则与模式1.pptx

    ### 软件工程中的软件设计原则与模式 #### 第一章:软件设计原则与模式概述 ##### 软件设计原则介绍 软件设计原则是在软件开发过程中为提高软件的质量和可维护性而遵循的一系列设计准则。这些原则旨在帮助开发...

    软件工程中的软件设计原则与模式讲解详评.pptx

    ### 软件工程中的软件设计原则与模式详解 #### 第一章:软件工程概述 **1.1 软件工程简介** 软件工程是一门跨学科领域,它结合了计算机科学、工程学以及管理学等多个领域的知识和技术,旨在解决软件开发过程中...

    各软件设计原则在本项目中的应用1

    在本项目中,软件设计原则的应用对于代码的结构和可维护性起到了关键作用。以下是各个原则的具体体现: 1. **单一职责原则**:遵循这一原则,项目中的`controller`类被设计为各自拥有一个明确的职责。例如,`...

    软件设计原则与设计模式.pptx

    软件设计原则与设计模式.pptx

    读书笔记:软件设计原则与设计模式 Java实现.zip

    读书笔记:软件设计原则与设计模式 Java实现

    软件工程与软件系统设计原则.pptx

    #### 第三章:软件设计原则 **设计原则的重要性:** 良好的设计原则对于构建高质量、可维护的软件至关重要。它们帮助开发者: - **优化软件架构:**确保系统结构合理,易于理解和扩展。 - **提高代码质量:**促进...

    1. 软件设计原则(1).md

    1. 软件设计原则(1).md

Global site tag (gtag.js) - Google Analytics