设计模式引言

51 阅读5分钟

1. 面向对象的好处

通过封装、继承、多态把程序的耦合度降低,使用设计模式使程序更加的灵活,容易修改,并且易于复用。可维护、可扩展、可复用。要做到代码的责任分解。

2. 单一职责原则

单一职责原则:就一个类而言,应该仅有一个引起它变化的原因。

如果一个类承担的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会消弱或者抑制这个类完成其他职责的能力。这种耦合会导致脆弱的设计,当变化发生时,设计会遭受到意想不到的破坏。

软件设计真正要做的许多内容,就是发现职责把那些职责相互分离。 如果你能够想到多于一个的动机去改变一个类,那么这个类就具有多于一个的职责,就应该考虑类的职责分离。做到单一职责,这样代码才是易维护、易扩展、易复用、灵活多样。

3. 开放-封闭原则

开放-封闭原则:软件实体(类、模块、函数等等),应该可以扩展,但是不可修改。 面对需求,对程序的改动是通过增加新代码进行的,而不是更改现有的代码。

何时应对变化:绝对的对修改关闭是不可能的,无论模块是多么的‘封闭’,都会存在一些无法对之封闭的变化。既然不可能完全封闭,设计人员必须对于它设计的模块应该对哪种变化封闭做出选择。它必须先猜测出最有可能发生的变化种类,最后构造抽象来隔离那些变化。

但事先预测是很难的,可以在最初编写代码时候,假设变化不会发生,但可以等到变化发生时立即采取行动,创建抽象来隔离以后发生的同类变化。

希望是在开发工作展开不久就知道可能发生的变化。察觉可能发生的变化所等待的时间越长,要创建正确的抽象就越困难。应该仅对应用程序中呈现出频繁变化的那些部分抽象,但对于应用程序中每个部分都刻意地进行抽象并不是一个好主意。拒绝不成熟的抽象和抽象本身一样重要。

4. 依赖倒转原则

依赖倒转原则:抽象不应该依赖细节,细节应该依赖于抽象,就是要针对接口编程, 不要针对实现细节编程,反之就是过程化的设计。即程序中所有依赖关系都是终止于抽象类或者接口。

高层模块不应该依赖低层模块,两个都应该依赖抽象。抽象不应该依赖细节,细节应该依赖抽象。

5. 里氏代换原则

里氏代换原则:子类型必须能够替换掉它们的父类。

由于子类型的可替换性才使得使用父类类型的模块在无需修改的情况下就可以扩展,使得开放-封闭成为了可能。

6. 迪米特法制

迪米特法则也叫最少知识原则:如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。

迪米特法则首先强调的前提是在类的结构设计上,每一个类都应当尽量降低成员的访问权限。迪米特法则其根本思想是强调了类之间的松耦合。类之间的耦合越弱,越有利于复用,一个处在弱耦合的类被修改,不会对有关系的类造成波及。

7. 合成(组合)/聚合复用原则

合成(组合)/聚合复用原则:尽量使用合成/聚合,尽量不要使用类继承。

因为对象的继承关系是在编译时就定义好了,所以无法在运行时改变从父类继承的实现。子类的实现与它的父类有非常紧密的依赖关系,以至于父类实现中的任何变化必然会导致子类发生变化。当需要复用子类时,如果继承下来的实现不适合解决新的问题,则父类必须重写或被其他更合适的类替换。这种依赖关系限制了灵活性并最终限制了复用性。

优先使用对象的合成(组合)/聚合将有助于保持每个类被封装,并被集中在单个任务上。这样类和类继承层次会保持较小规模,并且不太可能增长为不可控制的庞然大物。

例如:手机品牌为父类,继承子类有手机品牌M,手机品牌N,它们又为父类被继承,又有各自品牌下的通讯录、游戏。如果增加很多品牌很多功能就会变成庞然大物。

所以手机品牌和手机软件它们之间是聚合关系。

继承是一种强耦合的结构,父类变,子类就必须要变。所以在使用继承的时候,一定要在是‘is-a’的关系时再考虑使用,而不是任何时候都去使用。

is-a从字面上看就表示"是一个"的意思,根据继承的特性一个派生类对象可以看成是一个基类对象,也就是说一个派生类对象"是一个"基类对象,所以这种名称符合对这种特性的概括。它没有所谓的全称,这是一种约定俗成的说法。与此对应还有一种类与的类的关系叫has-a,表示"有一个",这种关系就是组成关系,指的是一个类将另一个类的对象作为自己的数据成员。