设计模式前言:面向对象设计指导原则

在开始学习设计模式,还有个必须要说的点就是面向对象的指导原则,我之前理清了对象之间的六大关系,在现实生活中这六大关系错综复杂,就像UML图中一样,各个对象被各种莫名其妙的线连在一起,你中有我,我中有你,剪不断,理还乱,看了都头大。还有莫名其妙的需求,有时根据需求要改一大片,甚至可能要重写。不难想象很多程序员就是这样猝死的2333.

************************************************************************************************************************

当然也有不想猝死的程序员,想在上班时间就把工作做完的程序员,他们就开始研究如何让代码更易维护,更易扩展,写起来更快(复用),如果要修改尽量不动以前已经运行很长时间没有错误的代码。虽然性能上会有所影响,但是比起猝死,比起早点下班,这不算什么。世界那么大我想去看看。但是对于程序员来说,想不加班,不存在的,但至少不会猝死。

于是设计模式就这样诞生了,至少我是这么认为的。但是设计模式会增加程序的复杂度,会降低程序的运行速度,对于第一次阅读你的代码,不太懂设计模式的人来说,这是一场灾难,调试的时候,一会跳到这,一会跳到那,头皮发麻。所以也不要太滥用设计模式,写好你的注释,画好你的UML图。人类不要互相伤害。

说的半天,我们赶紧把话题调回来,虽然常用的设计模式有多达23种,但是他们都有统一的设计原则,也就是面向对象设计指导原则,还有个前提要说什么是对象,一个对象对象是一组状态和一系列行为的组合体状态是对象的内在特性,行为是对象的外在特性。我这里学到的是6大设计原则。

*************************************************************************************************************************

不用看我后面罗里吧嗦的,没啥意思,都是些笔记。我们一句话一个设计原则,先记下来。

0.开闭原则:对扩展开放,对修改关闭。面向设计终极目标

1.单一职责原则:一个类应该只有一个职责。划清责任界限,哪里有错找哪里,清清楚楚。

2.里氏替换原则:基类可以使用的地方,子类也能使用。能满足这个再用继承。

3.依赖倒置原则:高层模块不应该依赖底层模块,应该依赖于抽象。依赖抽象,不依赖细节。细节依赖抽象。抽象不依赖细节。

4.最少知识原则:尽可能少的和其他实体发生关系。不要和陌生人说话。这样当修改时,影响少,扩展易

5.接口隔离原则:接口必须满足单一职责原则。只提供需要的行为。每个接口不存在子类用不到却必须实现的方法,如果不然,就要将接口拆分。

6.合成复用原则:多用组合和聚合,少用实现和继承。我上篇博文中这些关系应该说的很清楚

最后看起来好像依赖倒置原则和里氏替换原则重复了,都好像是一个意思。这里我找的一段区别讲的挺好的。

里氏替换原则和依赖倒置原则的区别:

两者定义不同,里氏替换原则是关于子类和父类的原则,依赖倒置原则是关于抽象与细节的原则。

两者应用范围不同,依赖倒置原则比里氏替换原则使用范围更广。

涉及对象关系不同,里氏替换原则种的子类具有自己的独立性,依赖倒置原则中的细节依赖于抽象。

两者所站的角度不同,其中里氏替换原则是站在模式对象一方,而依赖倒置原则是站在客户程序一方,模式对象一方将"相应多变的"子类视同它的接口看待,而客户程序一方依赖的内容不是“相对多变的”子类,而是“相对稳定的”接口。

上面说接口隔离原则和单一原则重复了,其实也并不是说重复了,还是有区别的。

接口隔离原则与单一职责原则的区别:

接口隔离原则与单一职责原则审视的角度不同,单一职责原则要求的是类与接口的职责单一,注重的是职责,这是业务上的划分。

接口隔离原则的意思是:每个接口不存在子类用不到却必须实现的方法,如果不然,就要将接口拆分。使用多个隔离的接口,要比使用单个接口(多个接口方法集合到一个接口)要好。

接口隔离原则则要求接口的方法尽量少,避免接口污染。

最后明明说六大原则,怎么写了七个。我也不知道为啥写了八个2333.

其实应该这样说,开闭原则是总原则,具体的实现原则是其他六个。

最后我开始刷一遍23种设计模式,而我要写的则偏向应用,尽量使用UML图,代码能少写就少写,重要的是他的设计思路以及它能解决什么问题。相关环境是游戏开发,使用引擎是 Unity。

面向对象设计是终生的学问。不是几句话能概括的。后面是我记得笔记,其实这些东西网上搜一大堆,而且比我记得笔记要好的多,我纯粹是水字数,啦啦啦啦

****************************************************************************************************************************

一.单一职责原则:你是哪个类,你负责什么,你就只负责什么,你需要什么就跟别的组件进行交互。
定义:一个对象应该只包含单一的职责,并且该职责被完整的封装在一个类中。
         就一个类而言,应该仅有一个能引起它变化的原因。
分析:1.一个类(或者大道模块,小到方法)承担的职责越多,它被复用的可能性越小,而且如果一个类承担的职责过多
,就相当于将这些职责耦合在一起,当其中一个职责变化时,可能会影响其他职责的运作。
         2.类的职责主要包括两个方面:数据职责和行为职责,数据职责通过其属性来体现,而行为职责通过其方法来体现。
        3.单一职责原则是实现高内聚,低耦合的指导方针,在很多代码重构手法中都能找到它的存在,它是最简单又最难
运用的原则,需要设计人员发现类的不同职责并将其分离,而发现类的多重职责需要设计人员具有较强的分析设计能力
和相关重构经验。
******************************************************************************************************************

二.开-闭原则:对扩展开放,对修改关闭。面对需求,对程序的改动是通过增加新代码进行的,而不是改变原来的代码。

他是面向对象设计的终极目标。

*****************************************************************************************************************
三.里氏代换原则:如果能够使用基类对象,那么使用其子类不会报错正常运行,反之不一定。
定义:1.如果每一个类型为S的对象o1,都有类型为T的对象o2,使得以T定义的所有程序P在所有的对象o1都代换成o2时,程序
P的行为没有变化,那么类型S是类型T的子类型。
         2.所有引用基类(父类)的地方必须能透明的使用其子类的对象。
          在软件中如果能够使用基类对象,那么一定能够使用其子类对象,把基类都替换成它的子类,程序将不会产生任何错误
和异常,反过来则不成立,如果一个软件实体使用的是一个子类的话,那么它不一定能够使用基类。
         里氏代换原则是实现开闭原则的重要方式之一,由于使用基类对象的地方都可以使用子类对象,因此在程序中尽量
使用基类类型来对对象进行定义,而在运行时再确定其子类类型,用子类对象来替换父类对象。
****************************************************************************************************************

四.依赖倒置原则:高层模块不依赖底层模块,针对接口编程,不要针对实现编程。

A.高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象。

B.抽象不应该依赖于具体,具体应该依赖于抽象。

*****************************************************************************************************************
五.接口隔离原则:
定义:1.客户端不应该依赖那些它不需要的接口
          2.一旦一个接口太大,则需要将它分割成一些更细小的接口,每一个接口应该承担一种相对独立的角色,不多不少
,不干不该干的事,该干的事都要干。
          3.使用接口隔离原则拆分接口时,首先必须满足单一职责原则,将一组相关的操作定义在一个接口中,且
在满足高内聚的前提下,接口中的方法越少越好。
          4.可以在进行系统设计时采用定制服务的方式,即为不同的客户端提供宽窄不同的接口,只提供需要的行为,
而隐藏用户不需要的行为。
*****************************************************************************************************************
六.最少知识原则(迪米特法则)
1.定义:
每一个软件单位对其他的单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位。
2.分析:
     1.迪米特法则就是指一个软件实体应当尽可能少的与其他实体发生相互作用。这样,当一个模块修改时,就会尽量少的
影响其他的模块,扩展会相对容易,这是对软件实体之间通信的限制,它要求限制软件实体之间通信的宽度和深度。
      2.狭义的迪米特法则:可以降低类之间的耦合,但是会在系统中增加大量的小方法并散落在系统的各个角落,它可以
使一个系统的局部设计简化,因为每一个局部都不会和远距离的对象有直接的关联,但是也会造成系统的不同模块之间
的通信效率降低,使得系统的不同模块之间不容易协调。
     3.广义的迪米特法则:指对象之间的信息流量,流向以及信息的影响的控制,主要是对信息隐藏的控制。信息的隐藏可以
使各个子系统之间脱耦,从而允许它们独立的被开发,优化,使用和修改,同时可以促进软件的复用,由于每一个模块
都不依赖于其他模块而存在,因此每一个模块都可以独立的在其他的地方使用,一个系统的规模越大,信息的隐藏越重要,
而信息隐藏的重要性也就越明显。
      4.迪米特法则的主要用途在于控制信息的过载。
1.在类的划分上,应当尽量创建松耦合的类,类之间的耦合度越低,越有利于复用,一个处在松耦合中的类一旦被修改,
不会对关联的类造成太大波及。
2.在类的结构设计上,每一个类都应当尽量降低成员变量和成员函数的访问权限。
3.在类的设计上,只要有可能,一个类型应当设计成不变类。
4.在对其他类的引用上,一个对象对其他对象的引用应当降到最低。
*****************************************************************************************************************
七.合成复用原则:少用继承多用组合(合成复用)
定义:1.尽量使用对象组合,而不是继承来达到复用的目的。
分析:
          1.合成复用原则就是指在一个新的对象里通过关联关系(包括组合关系和聚合关系)来使用一些已有的对象,使之
成为新对象的一部分;新对象通过委派调用已有对象的方法达到复用其已有功能的目的。简言之:要尽量使用组合/聚合
关系,少用继承。
          2.在面向对象设计中,可以通过两种基本方法在不同的环境中复用已有的设计和实现,即通过组合/聚合关系或
通过继承。
          a)继承复用:实现简单,易于扩展。破坏系统的封装性;从基类继承而来的实现是静态的,不可能在运行时发生改变
,没有足够的灵活性;
         b)组合/聚合复用:耦合度相对较低,选择性的调用成员对象的操作,可以在运行时动态进行。("黑箱"复用)
          3.组合/聚合可以使系统更加灵活,类与类之间的耦合度降低,一个类的变化对其他类造成的影响相对较少,
因此一般首选使用组合/聚合来实现复用;其次才考虑继承,在使用继承时,需要严格遵循里氏替换原则,有效使用继承
会有助于对问题的理解,降低复杂度,而滥用继承反而会增加系统构建和维护的难度以及系统的复杂度,因此需要慎重
使用继承复用。
*****************************************************************************************************************
上述原则的作用:让自己设计实现出来的软件系统更加稳定,容易维护,并具有一致性。

封装性更好,复用性更高,易于维护。

面向对象是一门大学问,而学习设计模式可以让自己更快的理解,避免猝死。后面就是常用设计模式的讲解,不应该说成是笔记。













猜你喜欢

转载自blog.csdn.net/q493201681/article/details/80826330