设计模式的7原则及23种设计模式概要

来源:互联网 发布:网易数据分析师笔试题 编辑:程序博客网 时间:2024/06/04 23:24

一、设计模式的原则

1.开放封闭原则

        开放封闭原则(OCP,Open Closed Principle)是所有面向对象原则的核心。软件设计本身所追求的目标就是封装变化、降低耦合,而开放封闭原则正是对这一目标的最

直接体现。其他的设计原则,很多时候是为实现这一目标服务的,例如以Liskov替换原则实现最佳的、正确的继承层次,就能保证不会违反开放封闭原则。

        关于开放封闭原则,其核心的思想是:

        软件实体应该是可扩展,而不可修改的。也就是说,对扩展是开放的,而对修改是封闭的。

        因此,开放封闭原则主要体现在两个方面:

        1.对扩展开放,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况。

        2.对修改封闭,意味着类一旦设计完成,就可以独立完成其工作,而不要对类进行任何修改。

        “需求总是变化”、“世界上没有一个软件是不变的”,这些言论是对软件需求最经典的表白。从中透射出一个关键的意思就是,对于软件设计者来说,必须在不需要对原有系

统进行修改的情况下,实现灵活的系统扩展。而如何能做到这一点呢?

         只有依赖于抽象。实现开放封闭的核心思想就是对抽象编程,而不对具体编程,因为抽象相对稳定。让类依赖于固定的抽象,所以对修改就是封闭的;而通过面向对象的

继承和对多态机制,可以实现对抽象体的继承,通过覆写其方法来改变固有行为,实现新的扩展方法,所以对于扩展就是开放的。这是实施开放封闭原则的基本思路,同时这种

机制是建立在两个基本的设计原则的基础上,这就是Liskov替换原则和合成/聚合复用原则。对于违反这一原则的类,必须进行重构来改善,常用于实现的设计模式主要有

Template Method模式和Strategy模式。而封装变化,是实现这一原则的重要手段,将经常发生变化的状态封装为一个类。

2.依赖倒置原则

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

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

         依赖倒置原则(Dependence Inversion Principle)是程序要依赖于抽象接口,不要依赖于具体实现。简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降

低了客户与实现模块间的耦合。面向过程的开发,上层调用下层,上层依赖于下层,当下层剧烈变动时上层也要跟着变动,这就会导致模块的复用性降低而且大大提高了开发的

成本。面向对象的开发很好的解决了这个问题,一般情况下抽象的变化概率很小,让用户程序依赖于抽象,实现的细节也依赖于抽象。即使实现细节不断变动,只要抽象不变

客户程序就不需要变化。这大大降低了客户程序与实现细节的耦合度。

3.迪米特法则

         迪米特法则可以简单说成:talk only to your immediate friends。 对于OOD来说,又被解释为下面几种方式:一个软件实体应当尽可能少的与其他实体发生相互作用。每

一个软件单位对其他的单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位。

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

迪米特法则不希望类之间建立直接的联系。如果真的有需要建立联系,也希望能通过它的友元类来转达。因此,应用迪米特法则有可能造成的一个后果就是:系统中存在大量的

中介类,这些类之所以存在完全是为了传递类之间的相互调用关系——这在一定程度上增加了系统的复杂度。有兴趣可以研究一下设计模式的门面模式(Facade)和中介模式

(Mediator),都是迪米特法则应用的例子。

4.单一职责原则

        所谓职责是指类变化的原因。如果一个类有多于一个的动机被改变,那么这个类就具有多于一个的职责。而单一职责原则就是指一个类或者模块应该有且只有一个改变的原

因。一个类,只有一个引起它变化的原因。应该只有一个职责。每一个职责都是变化的一个轴线,如果一个类有一个以上的职责,这些职责就耦合在了一起。这会导致脆弱的设

计。当一个职责发生变化时,可能会影响其它的职责。另外,多个职责耦合在一起,会影响复用性。例如:要实现逻辑和界面的分离。

         之所以会出现单一职责原则就是因为在软件设计时会出现以下类似场景:负责两个不同的职责:职责P1,职责P2。当由于职责P1需求发生改变而需要修改类T时,有可能

会导致原本运行正常的职责P2功能发生故障。也就是说职责P1和P2被耦合在了一起。

5.接口隔离原则

        使用场合,提供调用者需要的方法,屏蔽不需要的方法.满足接口隔离原则.比如说电子商务的系统,有订单这个类,有三个地方会使用到,一个是门户,只能有查询方法,一个是外部

系统,有添加订单的方法,一个是管理后台,添加删除修改查询都要用到.根据接口隔离原则(ISP),一个类对另外一个类的依赖性应当是建立在最小的接口上.也就是说,对于门户,它只

能依赖有一个查询方法的接口.


6.优先原则(优先使用组合而不是继承)

         面向对象系统中功能复用的两种最常用技术是类继承和对象组合(object composition)。正如我们已解释过的,类继承允许你根据其他类的实现来定义一个类的实现。这种

通过生成子类的复用通常被称为白箱复用(white-box reuse)。术语“白箱”是相对可视性而言:在继承方式中,父类的内部细节对子类可见。对象组合是类继承之外的另一种复用

选择。新的更复杂的功能可以通过组装或组合对象来获得。对象组合要求被组合的对象具有良好定义的接口。这种复用风格被称为黑箱复用(black-box reuse),因为对象的内部

细节是不可见的。对象只以“黑箱”的形式出现。

        继承和组合各有优缺点。类继承是在编译时刻静态定义的,且可直接使用,因为程序设计语言直接支持类继承。类继承可以较方便地改变被复用的实现。当一个子类重定义

一些而不是全部操作时,它也能影响它所继承的操作,只要在这些操作中调用了被重定义的操作。

        但是类继承也有一些不足之处。首先,因为继承在编译时刻就定义了,所以无法在运行时刻改变从父类继承的实现。更糟的是,父类通常至少定义了部分子类的具体表示。因为继承对子类揭示了其父类的实现细节,所以继承常被认为“破坏了封装性”。子类中的实现与它的父类有如此紧密的依赖关系,以至于父类实现中的任何变化必然会导

致子类发生变化。当你需要复用子类时,实现上的依赖性就会产生一些问题。如果继承下来的实现不适合解决新的问题,则父类必须重写或被其他更适合的类替换。这种依赖关

系限制了灵活性并最终限制了复用性。一个可用的解决方法就是只继承抽象类,因为抽象类通常提供较少的实现。

        对象组合是通过获得对其他对象的引用而在运行时刻动态定义的。组合要求对象遵守彼此的接口约定,进而要求更仔细地定义接口,而这些接口并不妨碍你将一个对象和其

他对象一起使用。这还会产生良好的结果:因为对象只能通过接口访问,所以我们并不破坏封装性;只要类型一致,运行时刻还可以用一个对象来替代另一个对象;更进一步,

因为对象的实现是基于接口写的,所以实现上存在较少的依赖关系。对象组合对系统设计还有另一个作用,即优先使用对象组合有助于你保持每个类被封装,并被集中在单个任

务上。这样类和类继承层次会保持较小规模,并且不太可能增长为不可控制的庞然大物。另一方面,基于对象组合的设计会有更多的对象 (而有较少的类),且系统的行为将依赖

于对象间的关系而不是被定义在某个类中。这导出了我们的面向对象设计的第二个原则:优先使用对象组合,而不是类继承。       

7.里氏替换原则

二、23种设计模式

1.创建型模式:用来处理对象的创建过程

(1)单例模式(Single Pattern)

(2)工厂模式(Factory Pattern)

(3)抽象工厂模式(Factory Pattern)

(4)建造者模式(Builder Pattern)

(5)原型模式(Prototype Pattern)

2.结构型模式:用来处理类和对象的组合

(6)代理模式(Proxy Pattern)

(7)装饰模式(Decorator Pattern)

(8)适配器模式(Adapter Pattern)

(9)桥接模式(Bridge Pattern)

(10)组合模式(Composite Pattern)

(11)外观模式(Facade Pattern)

(12)享元模式(Flyweight Pattern)

3.行为型模式:用来对类或对象怎么进行交互和怎样分配职责进行描述

(13)模板模式(Template Pattern)

(14)命令模式(Command Pattern)

(15)责任链模式(Chain of Responsibility Pattern)

(16)策略模式(Strategy Pattern)

(17)中介者模式(Mediator Pattern)

(18)观察者模式(Observer Pattern)

(19)备忘录模式(Memento Pattern)

(20)访问者模式(Visitor Pattern)

(21)状态模式(State Pattern)

(22)解释器模式(Interpreter Pattern)

(23)迭代器模式(Iterator Pattern)


0 0