初识设计模式、软件设计的六大原则

总结:本篇文字分为两个部分。第一部分:设计模式基本常识;第二部分:软件设计中的六大原则,并详细分析了单一职责原则。(本篇文章的时间轴参考:为知笔记支撑文件夹\Java设计模式(时间序列图).vsdx)

部分一:初识设计模式

什么是设计模式?James拿到这个论点时,很是迷惑!

模式?是不是一个模子?模式识别——计算机领域的经典问题?

设计模拟?软件的设计模式?不懂!!!

但是在实际编码、调试过程中,James的遇到过很是难解的问题:工程代码中有过多的冗余代码——代码复用性不高;需求一旦改变,需要更改很多地方的代码逻辑——代码灵活性不强……

那先看看设计模式的概念吧!

设计模式是一套被反复使用、为多数人知晓、经过分类编目的、代码设计经验的总结。为了编写可重用性代码,让代码更容易被他人理解,并保证代码可靠性而使用的设计思想。

设计模式使代码编制真正工程化。

设计模式是软件行业智慧积累的结晶;它提出了一系列标准术语,概括了相关行业中经验丰富的从业者所应用的所有概念和方法。

常用的23种设计模式如下:

1.单例模式;

2.工厂方法模式; 

3.抽象工厂模式; 

4.模版方法模式; 

5.建造者模式; 

6.代理模式; 

7.原型模式; 

8.中介者模式; 

9.命令模式; 

10.责任链模式; 

11.装饰模式; 

12.策略模式; 

13.适配器模式; 

14.迭代器模式; 

15.组合模式; 

16.观察者模式; 

17.门面模式; 

18.备忘录模式;

19.访问者模式; 

20.状态模式; 

21.解释器模式; 

22.享元模式; 

23.桥梁模式;

设计模式的起源是面向对象程序设计思想,是面向对象设计的精髓——抽象;面向对象通过类和对象来实现抽象,实现时产生了面向对象的三种重要机制:封装、继承和多态而这三种机制衍生了各式各样的设计模式。

在运用面向对象思想进行软件设计时,需要遵循以下原则:

1. 单一责任原则;

2. 里氏替换原则;

3. 依赖倒置原则;

4. 接口隔离原则;

5. 迪米特法原则;

6. 开闭原则;

这23种设计模式按设计意图可组织成五类:接口型模式,责任型模式、构造型模式,操作型模式以及扩展型模式模式的设计意图指出了应用一个模式的价值所在。但上面所说的23中的某种设计模式,并不是仅仅支持一种设计意图。

在软件设计过程中,只要我们尽量遵循以上设计原则,设计出来的软件一定是优秀的,且足够健壮、稳定,并有足够的灵活性来迎接需求的变更。

那James还是不知道为什么,比如:这些原则的含义是什么?它们为什么而出现,解决了什么工程问题?这些原则和之前讲述的23种设计模式有什么联系?如何在我们的工程代码中使用……

这些疑问都需要James一一解决,不过James相信自己肯定能够战胜这些困难。(纵使是住着握手楼、吃着方便面、挤着公交车,只要能够活下来,就有希望!别人能做出来的东西,自己为什么不行?要有必胜的信心!)

部分二:从设计原则开始——单一职责原则

单一职责原则:应该有且仅有一个原因引起类的变更。

为什么在这里出现的是类?是不是仅仅只应用于类的设计?

(为什么会出现这种设计原则?)当一个类承担了过多的职责,就等于把这些职责耦合在一起,一个职责的变化可能会削弱或者一直这个类完成其他职责的能力。问题就出在耦合性上!

软件设计真正要做的工作是:发现职责并把那些职责互相分离。单一职责可使类的复杂性降低,其实现的工作有明确且清晰的定义。

那问题来了,James不明白什么是“类的变更”?

(如何实践单一职责原则?)考虑到如何使用代码实现单一责任原则(代码即是思路嘛),好在有百度和谷歌。下面就使用网站上的例子讲解,James认为:用这个例子比较容易说明问题。

需求分析:烹饪,做一道鱼香茄子。

public interface Cooking {
    // 获取菜名
    String getCookingName();
    void setCookingName(String cookingName);

    // 烹饪之前的准备工作:摘菜、洗菜等等,准备相应的食材
    void doPrepare(String vegetableName);

    // 烹饪模式:蒸、煮、炒、炸等,并提供菜名
    void doFire(String cookingName, String mode);
}

如果James想要烹饪一道鱼香茄子,可以覆写以上四个方法,从获知菜名、准备食材到具体的烹饪操作。从信息和行为的角度来说,前面两个方法是鱼香茄子相关的信息,后两个则是相关的行为(烹饪具体的行为)。

如果考虑如下方式是否更完善?

public interface ICookingInfo {
    // 获取菜名
    String getCookingName();
    void setCookingName(String cookingName);
}
public interface ICookingFire {
    // 烹饪之前的准备工作:摘菜、洗菜等等,准备相应的食材
    void doPrepare(ICookingInfo info);

    // 烹饪模式:蒸、煮、炒、炸等,并提供菜名
    void doFire(ICookingInfo info, String mode);
}

Cooking类包含两个部分,一个部分的职责是获取菜名及相关信息(口味、特点…),另一个部分的职责是具体烹饪(当然需要菜名相关信息啦)

如果ICookingInfo发生改变,势必会造成ICookingFire的改变。对于职责不同的两个部分,需要拆分。那在Cooking类中,只需要实现上述两个不同接口,即可实现烹饪一道菜的功能。

public class Cooking implements ICookingInfo, ICookingFire {
    @Override
    public String getCookingName() {
        return null;
    }

    @Override
    public void setCookingName(String cookingName) {

    }

    @Override
    public void doPrepare(ICookingInfo info) {

    }

    @Override
    public void doFire(ICookingInfo info, String mode) {

    }

}

产生了Cooking对象后,可将其视为ICookingInfo或者ICookingFire接口使用;如果需要设置菜名或其他信息,可以当做是ICookingInfo的实现类;要是进行烹饪操作,就当做是ICookingFire的实现类。(突然引出了一个问题:James貌似不太理解类和其实现的接口之间的关系……)

总之,在接口设计中,如果接口可细分为不同的“职责”,就可将该接口进一步细分。

上述仅仅只是从接口角度解读了:单一职责原则,此外还可以用在类的设计、方法的定义上。归结为一点:自己的事情自己做,并承担相应的责任。

可参考一下实例分析:

1. http://blog.csdn.net/zhengzhb/article/details/7278174 从类的角度解读;

2. 待续……

单一职责原则的优点:

1. 类的复杂性降低,实现什么职责都有清晰明确的定义;

2. 可读性提高;

3. 可维护性提高;

4. 变更引起的风险降低;如果接口的单一职责做得好,一个接口修改只对相应的实现类有影响,对其他的接口无影响,对系统的扩展性、维护性都有非常大的帮助

单一职责原则提出了一个编写程序的标准,用“职责”或“变化原因”来衡量接口或类设计得是否优良,但是“职责”和“变化原因”都是不可度量的,因项目而异,因环境而异。

单一职责原则可以使用到哪些方面?单一职责原则适用于接口、类,同样适用于方法(一个方法尽可能只做一件事情)。接口一定要做到单一职责,类的设计尽量做到只有一个原因引起变化。

但凡事都有需要权衡利弊的地方,不能因为生搬硬套单一职责原则,而让系统变得繁杂而庞大。

时间: 2024-10-19 21:43:57

初识设计模式、软件设计的六大原则的相关文章

设计模式 之 设计的 六大原则(6) 开放封闭原则

  开放封闭原则  定义:一个软件实体如类.模块和函数应该对扩展开放,对修改关闭. 问题由来:在软件的生命周期内,因为变化.升级和维护等原因需要对软件原有代码进行修改时,可能会给旧代码中引入错误,也可能会使我们不得不对整个功能进行重构,并且需要原有代码经过重新测试. 解决方案:当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化. 开闭原则是面向对象设计中最基础的设计原则,它指导我们如何建立稳定灵活的系统.开闭原则可能是设计模式六项原则中定义最模糊的一个了,

设计模式 之 设计的 六大原则(3) 依赖倒置原则

依赖倒置原则 定义:高层模块不应该依赖低层模块,二者都应该依赖其抽象:抽象不应该依赖细节:细节应该依赖抽象. 问题由来:类A直接依赖类B,假如要将类A改为依赖类C,则必须通过修改类A的代码来达成.这种场景下,类A一般是高层模块,负责复杂的业务逻辑:类B和类C是低层模块,负责基本的原子操作:假如修改类A,会给程序带来不必要的风险. 解决方案:将类A修改为依赖接口I,类B和类C各自实现接口I,类A通过接口I间接与类B或者类C发生联系,则会大大降低修改类A的几率. 依赖倒置原则基于这样一个事实:相对于

设计模式 之 设计的 六大原则(4) 接口隔离原则

接口隔离原则 定义:客户端不应该依赖它不需要的接口:一个类对另一个类的依赖应该建立在最小的接口上. 问题由来:类A通过接口I依赖类B,类C通过接口I依赖类D,如果接口I对于类A和类B来说不是最小接口,则类B和类D必须去实现他们不需要的方法. 解决方案:将臃肿的接口I拆分为独立的几个接口,类A和类C分别与他们需要的接口建立依赖关系.也就是采用接口隔离原则. 举例来说明接口隔离原则: (图1 未遵循接口隔离原则的设计) 这个图的意思是:类A依赖接口I中的方法1.方法2.方法3,类B是对类A依赖的实现

软件设计6大原则

1.开闭-原则:对于一个软件实体(类,模块,函数等)来说,应该可以扩展,但不可以修改. 对于扩展是开放的(Open for extension),对于更改是封闭的(Closed for modification). 2.单一职责原则(SRP):就一个类而言,应该仅有一个引起它变化的原因. 软件设计就是要发现职责并且把这些职责相互分离,如果你可以想到多于一个的动机去改变一个类,那么这个类就具有多于一个的职责,就应该考虑类的职责分离. 3.迪米特法则 4.里氏代换原则 子类必须能够替换掉其父类. 例

综述:设计模式的分类及六大原则

一.设计模式的分类 总体来说设计模式分为三大类: 创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. 结构型模式,共七种:适配器模式.装饰器模式.代理模式.外观模式.桥接模式.组合模式.享元模式. 行为型模式,共十一种:策略模式.模板方法模式.观察者模式.迭代子模式.责任链模式.命令模式.备忘录模式.状态模式.访问者模式.中介者模式.解释器模式. 其实还有两类:并发型模式和线程池模式.用一个图片来整体描述一下: 二.设计模式的六大原则 1.开闭原则(Open Clo

Java面向对象设计的六大原则

这是设计模式系列开篇的第一篇文章.也是我学习设计模式过程中的总结.这篇文章主要讲的是面向对象设计中,我们应该遵循的六大原则.只有掌握了这些原则,我们才能更好的理解设计模式.我们接下来要介绍以下6个内容. 单一职责原则——SRP 开闭原则——OCP 里式替换原则——LSP 依赖倒置原则——DIP 接口隔离原则——ISP 迪米特原则——LOD 单一职责原则 单一职责原则的定义是就一个类而言,应该仅有一个引起他变化的原因.也就是说一个类应该只负责一件事情.如果一个类负责了方法M1,方法M2两个不同的事

网页设计之六大原则

随着互联网时代的快速发展,设计师不再只是为互联网创造漂亮美观的图片那么简单了,作为一个WEB设计师,除了基本的设计技能之外,还需要考虑一些其他的问题,比如用户体验,算法,代码等等.如今用户体验设计越来越重要,对于WEB表单的设计尤其如此. WEB表单设计的目标是设计出一套让用户能够从填表到点击提交按钮的最简单的流程.从非常简单直接的表单到花哨.多彩和创意的表单,每个网站都会呈现一种表单风格.不论是登录/注册表单,还是联系表单,或者其他类型表单,设计师们需要牢记一点:这些表单的目标是要赢得用户的注

【软件设计】六大设计原则讲解

1. 单一职责原则 -Single Responsibility Principle SRP,Single Responsibility Principle: There should never be more than one reason for a class to change. 应该有且仅有一个原因引起类的变更.(如果类需要变更,那么只可能仅由某一个原因引起) 问题由来: 类T负责两个不同的职责:职责P1,职责P2.当由于职责P1需求发生改变而需要修改类T时,有可能会导致原本运行正常

设计模式-软件设计原则4-接口隔离原则

接口隔离原则(InterfaceSegregationPrinciple,ISP)是指用多个专门的接口,而不使用单一的总接口,客户端不应该依赖它不需要的接口.这个原则指导我们在设计接口时应当注意一下几点:1.一个类对一类的依赖应该建立在最小的接口之上.2.建立单一接口,不要建立庞大臃肿的接口.3.尽量细化接口,接口中的方法尽量少(不是越少越好,一定要适度).接口隔离原则符合我们常说的高内聚低耦合的设计思想,从而使得类具有很好的可读性.可扩展性和可维护性.我们在设计接口的时候,要多花时间去思考,要