设计模式原则

1:单一职责原则

单一职责原则:一个类只负责一个功能领域中的相应职责,或者可以定义为:就一个类而言,应该只有一个引起它变化的原因

换句话说就是一个接口只做一件事,即一个职责一个接口。但是困难的是划分职责时并没有一个标准,最终都是需要从实际的项目去考虑。我们在设计的时候,尽量单一,然后对于其实现类就要多方面的考虑。不能死套单一职责原则,否则会增加很多类,给维护带来不便。

单一职责原则是最简单的面向对象设计原则,它用于控制类的粒度大小

单一指责原则告诉我们:一个类不能太“累”,在软件系统中,一个类(大到模块,小到方法)承担的职责越多,它被复用的可能性就越小,而且一个类承担的职责过多,就相当于将这些职责藕合在一起,当其中一个职责变化时,可能会影响到其他职责的运作,因此要将这些职责进行分离,将不同的职责封装不同的类中,即将不同的变化原因封装在不用的类中,如果多个职责总是同时发生改变则可将它们封装在同一类中。

单一职责原则是实现高内聚,低耦合的指导方针,它是最简单也同时是最难运用的原则,需要开发人员发现类的不同职责从而将其分离。

2:里氏替换原则

在学习java类的继承时,我们知道继承有一些优点:

1:子类拥有父类的所有方法和属性,从而可以减少创建类的工作量。

2:提高了代码的重用性。

3:提高了代码的扩展性,子类不但拥有了父类的所有功能,还可以添加自己的功能。

但又有点也同样存在缺点:

1:继承是侵入性的。只要继承,就必须拥有父类的所有属性和方法。

2:降低了代码的灵活性。因为继承时,父类会对子类有一种约束。

3:增强了耦合性。当需要对父类的代码进行修改时,必须考虑到对子类产生的影响。有时修改了一点点代码都有可能需要对打断程序进行重构。

如何扬长避短呢?方法是引入里氏替换原则。

定义:

第一种定义:

如果对每一个类型为S的对象o1,都有类型为T的对象o2,使得以T定义的所有程序P在所有的对象o1都代换成o2时,程序P的行为没有发生变化,那么类型S是类型T的子类型。

第二种定义:

所有引用基类的地方必须能透明地使用其子类的对象。

通俗的说就是只要有父类出现的地方,都可以用子类来替代,而且不会出现任何错误和异常。但是反过来则不行,有子类出现的地方,不能用其父类替代。

里氏替换原则对继承进行了规则上的约束,这种约束主要体现在四个方面:

1:子类必须实现父类的抽象方法,但不得重写(覆盖)父类的非抽象(已实现)方法。

2:子类中可以增加自己特有的方法。

3:当子类覆盖或实现父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松(继承链上下层)。

4:当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。(子类重写或者实现父类的方法时,方法的返回值可以和父类一致,也可以比父类小(继承链下层))

3:依赖倒置原则

定义:

是程序要依赖于抽象接口,不要依赖于具体实现。简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户(调用者)与实现(实现者)模块间的耦合。(面向接口编程 所有的依赖都是依赖接口或者依赖抽象 维护,)

面向过程的开发,上层调用下层,上层依赖于下层,当下层剧烈变化时,上层也要跟着变化,这就会导致模块的复用性降低而且大大提高了开发的成本。 面向对象的开发很好的解决了这个问题,一般的情况下抽象的变化概率很小,让用户程序依赖于抽象,实现的细节也依赖于抽象。即使实现细节不断变化,只要抽象不变,客户程序就不需要变化。这大大降低了客户程序域实现细节的耦合度。

抽象不应该依赖细节,细节应该依赖于抽象。说白了,就是针对接口编程,不要针对实现编程。

依赖倒置原则包含三层含义:

1:高层模块不应该依赖低层模块,两者都应该依赖其抽象;

2:抽象不应该依赖细节;

3:细节应该依赖抽象。

依赖倒置有三种方式来实现(DI 依赖注入)

1、通过构造函数传递依赖对象; 比如在构造函数中的需要传递的参数是抽象类或接口的方式实现。

2、通过setter方法传递依赖对象; 即在我们设置的setXXX方法中的参数为抽象类或接口,来实现传递依赖对象。

3、接口声明实现依赖对象,也叫接口注入;

即在函数声明中参数为抽象类或接口,来实现传递依赖对象,从而达到直接使用依赖对象的目的。

原则:面向接口编程。抽象指的是接口或抽象类,细节就是具体的实现类,使用接口或者抽象类的目的是制定好规范和契约,而不去涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成。

注意:

1. 代码中传递参数或关联关系时,尽量引用高层的抽象层类,即使用接口和抽象类进行变量声明、参数类型声明、方法返回类型声明以及数据类型的转换;

2. 当一个对象和其他对象有依赖关系时,可以利用依赖注入的方法将类之间进行解耦,主要有:构造注入、Set方法注入和接口注入;

3. 开闭是原则,里氏是基础,依赖倒置是手段;

4. 低层模块尽量都要有抽象类或接口,或者两者都有;

5. 变量的声明类型尽量是抽象类或接口;

6. 使用继承时遵循里氏替换原则。

好处:

1. 可降低类之间的耦合性;

2. 可提高系统的稳定性;

3. 可降低修改程序所造成的风险。

在大多数情况下,这三个设计原则会同时出现,开闭原则是目标,里氏代换原则是基础,依赖倒转原则是手段,它们相辅相成,相互补充,目标一致,只是分析问题时所站角度不同而已。

4:接口隔离原则

1.定义: 建立单一接口,不要建立臃肿庞大的接口。即接口尽量细化,同时接口中的方法尽量少。在这里提一下单一职责和接口隔离原则的区别。首先两个侧重点是不一样的,

单一职责要求类和接口,或者方法的职责单一,侧重点在职责,这是根据业务逻辑进行划分的。而接口隔离原则要接口中的方法尽量少。比如,一个接口或者一个中有十个方法,不同的方法做不同的事情,但是这个接口总体就是处理一件事情,然后具体细分成了10个方法。不同的模块根据不同的权限进行访问,这是符单一职责原则的。但是按照接口隔离的原则是要求接口接口中的方法尽量少,落实到这个实例就是要求尽量多几个专门的接口供不同的模块使用,而不是只有一个臃肿的接口,依据权限去限制不同模块可以访问的方法。

  2.接口隔离原则是对接口定义的规范。含义主要包含以下4点。

  ①接口尽量小。根据具体业务把一个接口按照接口隔离原则细化成更多的接口。但是在此基础之上必须不能违背单一职责原则。

  ②接口要高内聚。高内聚的意思就是提高接口和类处理能力,减少对外的交互。接口是对外的承诺,因此设计时应该尽量少公布接口中的public方法,承诺越少系统开发越有利且变更风险就越少。

③定制服务。定制服务就是单独为一个个体提供服务,即只提供访问者需要的方法。

举一个图书管理系统的例子,有一个查询接口BookSearch,包括如下方法:searchById,searchByBookName,searchByCategory,complexSearch,其中前三个方法是提供给学生使用的,后一个方法是提供给管理员使用的,学生对这个方法的访问是有限制的,调用不会返回任何值。当这四个方法全部公布出去之后,学生对此方法的访问即使不返回任何值也会使服务器性能下降。因此合理的设计应该是拆分这个接口为两个接口:SimpleSearch和AdminSearch。SimpleSearch接口提供searchById,searchByBookName,searchByCategory方法,AdminSearch接口提供complexSearch方法,此时学生实现SimpleSearch接口即可,管理员同时实现SimpleSearch和AdminSearch两个接口。

  ④接口设计是有限度的。接口设计越小越好,但是结构同时会变得复杂,维护也变得难了。因此就要把握住这个度。

5: 迪米特法则

不要和陌生人说话,一个对象应当对其他对象有尽可能少的了解。一个软件实体应当尽可能少的与其他实体发生相互作用。每一个软件单位对其他的单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位。

迪米特法则的初衷在于降低类之间的耦合。由于每个类尽量减少对其他类的依赖,因此,很容易使得系统的功能模块功能独立,相互之间不存在(或很少有)依赖关系。

迪米特法则还有一个更简单的定义:只与直接的朋友通信

首先来解释一下什么是直接的朋友:每个对象都会与其他对象有耦合关系,只要两个对象之间有耦合关系,我们就说这两个对象之间是朋友关系。

耦合的方式很多,依赖、关联、组合、聚合等。其中,我们称出现成员变量、方法参数、方法返回值中的类为直接的朋友,而出现在局部变量中的类则不是直接的朋友。

也就是说,陌生的类最好不要作为局部变量的形式出现在类的内部。

迪米特法则不希望类之间建立直接的联系。如果真的有需要建立联系,也希望能通过它的友元类来转达。因此,应用迪米特法则有可能造成的一个后果就是:系统中存在大量的中介类,这些类之所以存在完全是为了传递类之间的相互调用关系——这在一定程度上增加了系统的复杂度。

迪米特法则还强调在类的结构设计上,每一个类都应当降低成员的访问权限,也就是说,一个类包装好自己的private状态,不需要让别的类知道的字段或行为就不要公开。

迪米特法则强调了下面两点:

1:从被依赖者的角度:只暴露应该暴露的方法或属性,即编写相关的类时确定方法和属性的权限

2:从依赖者的角度来看,只依赖应该依赖的对象

例如:用户关闭计算机()(saveCurrentTask() 保存当前的任务->closeService()(关闭计算机服务)->closeScreen()(关闭屏幕)->closePower()(关闭电源))

计算机类(用户只有一个操作,关机 就不要把上述四个方法都定义为public 用户挂你的需要调用四个步骤 closePower()à调用其它三个方法 可以把其他三个方法定义为private)

6:开闭原则

定义:一个软件实体如类、模块和函数应该对扩展开放,对改动关闭。

问题由来:在软件的生命周期内,由于变化、升级和维护等原因须要对软件原有代码进行改动时,可能会给旧代码中引入错误。也可能会使我们不得不正确整个功能进行重构,而且须要原有代码经过又一次測试。

解决方式:当软件须要变化时。尽量通过扩展软件实体的行为来实现变化。而不是通过改动已有的代码来实现变化。

开闭原则是面向对象设计中最基础的设计原则。它指导我们怎样建立稳定灵活的系统。开闭原则可能是设计模式六项原则中定义最模糊的一个了,它仅仅告诉我们对扩展开放,对改动关闭,但是究竟怎样才干做到对扩展开放。对改动关闭,并没有明白的告诉我们。

曾经,假设有人告诉我“你进行设计的时候一定要遵守开闭原则”。我会觉的他什么都没说,但貌似又什么都说了。由于开闭原则真的太虚了。

事实上。我们遵循设计模式前面5大原则,以及使用23种设计模式的目的就是遵循开闭原则。也就是说,仅仅要我们对前面5项原则遵守的好了,设计出的软件自然是符合开闭原则的。这个开闭原则更像是前面五项原则遵守程度的“平均得分”,前面5项原则遵守的好,平均分自然就高,说明软件设计开闭原则遵守的好。假设前面5项原则遵守的不好。则说明开闭原则遵守的不好。

开闭原则无非就是想表达这样一层意思:用抽象构建框架。用实现扩展细节。由于抽象灵活性好。适应性广,仅仅要抽象的合理。能够基本保持软件架构的稳定。而软件中易变的细节。我们用从抽象派生的实现类来进行扩展,当软件须要发生变化时,我们仅仅须要依据需求又一次派生一个实现类来扩展就能够了。当然前提是我们的抽象要合理,要对需求的变更有前瞻性和预见性才行。

讲到这里,再回忆一下前面说的5项原则。恰恰是告诉我们用抽象构建框架。用实现扩展细节的注意事项而已:单一职责原则告诉我们实现类要职责单一;里氏替换原则告诉我们不要破坏继承体系。依赖倒置原则告诉我们要面向接口编程。接口隔离原则告诉我们在设计接口的时候要精简单一。迪米特法则告诉我们要减少耦合。

而开闭原则是总纲。他告诉我们要对扩展开放,对改动关闭。

最后说明一下怎样去遵守这六个原则。

对这六个原则的遵守并非是和否的问题,而是多和少的问题,也就是说。我们一般不会说有没有遵守,而是说遵守程度的多少。不论什么事都是过犹不及,设计模式的六个设计原则也是一样,制定这六个原则的目的并非要我们刻板的遵守他们,而须要依据实际情况灵活运用。对他们的遵守程度仅仅要在一个合理的范围内,就算是良好的设计。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • 设计模式的基本原则 设计模式的基本原则非常重要,只要真正深入地理解了设计原则,很多设计模式其实就是原则的应用而已,...
    泥孩儿0107阅读 224评论 0 0
  • 一、单一职责原则(SRP) 定义:不要存在多于一个导致类变更的原因。通俗的说,即一个类只负责一项职责。 问题由来:...
    真心懒阅读 4,217评论 0 10
  • 设计模式(Design Pattern) 是什么是一套被反复使用、多数人知晓的、经过反复编写的、代码设计经验的总结...
    stoneyang94阅读 331评论 0 2
  • 目录: 设计模式六大原则(1):单一职责原则 设计模式六大原则(2):里氏替换原则 设计模式六大原则(3):依赖倒...
    加油小杜阅读 719评论 0 1
  • 如果每一次相遇 只是多了一次别离 我不迟不晚的到来 只是在挥手的瞬间不忘记 我哭泣,哭泣眼泪 心灵埋没记忆 如果每...
    2016冰山来客阅读 136评论 0 3