设计模式 ----- 开篇

老杨叔叔 2019-06-27


设计模式并非类库


为了方便地编写java程序,我们会使用类库,但设计模式不是类库。

与类型库相比,设计模式是一个更为普遍的概念。类库是由程序组合而成的组件,而设计模式则是来表现内

部组件是如何被组装的,以及每一个组件是如何通过相互关联构成一个庞大的系统。

                                                 -- 引用自《图解设计模式》 结城浩 著

起源


最早提出"设计模式"概念。是在1970年,由建筑设计大师亚力山大Alexander<<建筑的永恒之道>>描述:
     
模式是一条由三部分组成的通过规则:它表示了一个特定环境、一类问题和一个解决方案之间的关系。每一个 模

式描述了一个不断重复发生的问题,以及该问题解决方案的核心设计。在他的另一本书<<建筑者模式语言>>中提

到了现在已经定义的253种模式。

尽管Alexander的著作是针对建筑领域的,但他的观点适用于所以的工程设计领域,其中也包含软件设 计

领域。"软件设计模式",这个术语是由1990年代由Erich Gamma等2 从建筑设计领域引入到计算机科学中来的。

目前主要有23种。当然,设计模式不仅仅中有23种。

这里引用费马理论:光线传播的路径是需时最少的路径。而设计模式,在软件开发中,可以让我们少走很多

弯路,他是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。

软件需求变幻无穷,计划没有变化快,但是我们还是要寻找出不变的东西,并将它和变化的东西分离开来,

这需要非常的智慧和经验。设计模式是在这方面开始探索的一块里程碑。

为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。 设计模式使代码编写真正工程化;设计模

式是软件工程的基石脉络,如同大厦的结构一样

设计原则


#1 单一职责原则( Single Responsibility Principle )


"一个类仅有一个职责"或者"引起类变化的只有一个原因",这就是单一职责原理

就一个类而言,应该仅有仅有一个引起它变化的原因。简单来说,这个类应该是一组相关性很高的函数,数
     
据的封装。单一职责的划分界限并不是总那么清晰,很多的时候都是需要靠个人经验去界定。

类只因一个类的原因去变化,面对对象编程时,试图把一个事物对象成一个类,事务这个类具备的功能都是

这个类的操作。比如。1块钱,它既可以买辣条,它也可以去买小浣熊便利面等。而在单一职责原理下,钱的功能就

是引起这个类变化的两个原因,就应该写成两个类。

如果混在一起写,在修改的一个职责的时候,就会影响到另一个职责。当另一个类只使用其中一个职责的时
     
候,另一不会用到的职责会消耗更多的资源。

#2 开闭原则( Open Close Principle )


"对于扩展是开放的,对于修改是关闭的",这就是开闭原则原理

开闭原则明确的告诉我们:软件实现应该对扩展开放,对修改关闭,其含义就是说:一个软件应该通过

扩展来实现变化,而不是修改已有的代码来实现变化的。
     
     打个比方:1块钱,它既可以买2包辣条。但是由于物价上涨,现在只能买一块。那么根据开闭原则,你

并不能在原来的代码中去修改已有的代码。换句话说,现在是对已有代码的一种修改,但是,如果他现在还能

界定他还能买一根香肠。那么现在是对已经代码的一种扩展。

如果直接修改代码,那么如果他要换回去怎么办,又去改回来?所以,开闭原则可以提高程序的复用性、

维护性。

#3 里氏代换原则( Liskov Substitution Principle )


"任何基类可以出现的地方,子类一定可以出现。 里氏代换原则是继承复用的基石,只有当衍生类可以

替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新

的行为"。

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

上两点就是里氏代换原则。

打个比方:如果对每一个类型为"驼鸟"的对象a,都有类型为"鸟"的对象b,使得以"鸟"定义的所有程序C在
    
所有的对象a都代换为b,程序行为没有发生变化,那么类型"驼鸟"是"鸟"的子类型。只要有"鸟"能出现的地方

"驼鸟"也可以出现,而且替换为子类不会产生任何的Error或Exception,但是,"驼鸟"出现的地 方,"鸟"未

必就能适应。

#4 依赖倒转原则( Dependence Inversion Principle )


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

  • 抽象不依赖实现

  • 实现依赖抽象

以上三点就是依赖倒转的原则,什么意思呢?指的是模块与模块之间的信赖是通过抽象发生的,实现类之间
   
相互独立,之间不发生直接的信赖关系,其依赖关系是通过接口或者抽象类产生的,接口或者抽象类不依赖实现,

实现依赖接口或者抽象类。更加精简的意思叫做“面向接口编程” 。

采用依赖倒置原则可以减少类间的耦合性,提高系统的稳定性,减少并行开发引起的风险,提高代码的可读性

和可维护性。

这里打个比方:人,和一包笑笑牌辣条。创建一个人类A,里面有一个吃辣条的动作a1方法,再来一个笑笑

牌辣条类B,里面有一个打印辣条自己被吃的方法b1方法,再来一个终端,通过A.a1调用B.b1,这里我们可以发

现,这个人吃辣条这个场景,人类A和笑笑牌辣条类B之间是一个紧耦合的关系,假如我们这里还有一个只吃花生

的人,怎么办?如果这里把这个动作抽象化,定义一个接口C,接口C中有一个吃的方法,然后创建一个花生类,

里面有一个自己被吃的打印方法c1。以后如果还有别的功能,那么实现接口。就可以了。同理,如果这里人分为

大人和小人,那么就可以定义一个抽象类(人),然后再定义一个两个类大人和小孩,继承这个类。这样一来,

我们这个场景就可以减少类间的耦合性,提高系统稳定性,减少并行开发引起的风险,提高代码的可读性和可维

护性以为可扩展性。

#5 接口隔离原则( InterfaceSegregation Principles )


  • 客户端不应该依赖它不需要的接口

  • 一个类对另一个类的依赖应该建立在最小的接口上

这里的意思是建立单一的接口,接口尽量细化,如果有不需要的接口,客户端需要什么接口,就给什么接 

口,把不需要的接口剔除了。---

接口隔离原则与单一职责原则有什么区别


接口隔离原则与单一职现原则其实也没有,主要是角度不一样,单一职责原则要求类和接口只应该响应一

个变化,接口隔离原则要求接口的方法尽可能少,尽可能的去细化

总之呢:接口要尽量小,接口要高内聚,接口设计是有限度的。一个接口只服务一地一个子模块或者业务。

这个要划分开了,不要糅合在一起。接口要不断的精简,使之更加完善。如果接口是坏的,改之。如果背锅的

可能性大。就采用适配器去处理。尽量不要去背锅,这个会很难受。

#6 迪米特原则 ( Law of Demeter )


这个也叫最少知识原则(Low knowledge Principle)。最早是在1987年由美国Northeastern 

University的Ian Holland提出。类与类之间的关系越好(紧密),耦合度越高(大),当一个类发生改变时,

对另一个类的影响也越大。于是就提出了迪米特法则。通俗的来讲,就是一个类对自己依赖的类知道的越少越

好。也就是说,对于被依赖的类来说,无论逻辑多么复杂,都尽量地的将逻辑封装在类的内部,对外除了提供

的public方法,不对外泄漏任何信息。

打个比方,有一个辣条类,老板叫员工去清算辣条的包数。这里我们创建一个辣条类A,创建一个员工类B,

里面有一个接收辣条列表参数功能为清算辣条数量的方法b1。然后我们一个老板类C,里面有一个功能为命令

员工清算辣条的方法c1。里面初始化了辣条的数量。我们通过调用这个命令来达到清算辣条的数量。这里是我

们经常做的,没有不一样,但是我们可以发现,这里老板居然去初始化辣条。这里就有违反了迪米特原则。它

破坏了老板类的健壮性。我们只需要在老板类中写一个命令的方法就可以了,只调用员工清算的方法就可以了

,让main方法(客户端)去创建辣条。这样就保证了类与类之间的健壮性。

总之核心观念就是类间解耦,弱耦合,只有弱耦合后,类的复用率才可以提高。其结果就是产生了大量的

中转或跳转类,导致系统复杂,为维护带来了难度。所以,我们在实践时要反复权衡,即要让结构清晰,又做

到高内聚低耦合。

设计模式就是实现了这些原则,从而达到了代码复用、增加可维护性的目的

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

参考

几种常见的设计模式

如果有侵权,马上删除

相关推荐