设计模式原则及分类

Post on Aug 01, 2021 by Wei Lin

设计模式六大原则

包括:单一职责原则、接口隔离原则、依赖倒置原则、里氏替换原则、迪米特法则、开闭原则。

原则 内容
单一职责 一个类只负责一项职责
接口隔离 一个类对另一个类的依赖应该建立在最小的接口上面
依赖倒置 面向接口编程,各个类都应该依赖接口,而不是其它实现类
里氏替换 不要破坏继承体系,能使用父类的地方也可以使用子类
迪米特 降低类之间的耦合,对之间所依赖的类,依赖程度越小越好
开闭 通过扩展解决需求变动,而不是修改已有代码

单一职责原则

一个类只负责一项职责。如果要变更类,应该有且仅有一个原因引起类的变更。

原因:假如有类Class1完成职责T1,T2,当职责T1或T2有变更需要修改时,有可能影响到该类的另外一个职责正常工作。

优点:

  • 降低类的复杂度,一个类只负责一项职责,逻辑简单清晰;

  • 类的可读性,系统的可维护性更高;

  • 因需求变更引起的风险更低,降低对其它功能的影响。

接口隔离原则

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

建立单一接口,不要建立庞大臃肿的接口,尽量细化接口,接口中的方法尽量少。也就是说,我们要为各个类建立专用的接口,而不要试图去建立一个很庞大的接口供所有依赖它的类去调用。

原因:类A通过接口interface依赖类B(类A调用接口,类B实现接口),类C通过接口interface依赖类D,如果接口interface对于类A和类B来说不是最小接口,则类B和类D必须去实现他们不需要的方法。

依赖倒置原则

(1) 定义

  • 高层模块不应该依赖底层模块,二者都该应该依赖其抽象;

  • 抽象不应该依赖细节(实现类),细节应该依赖抽象。


通俗地说,依赖倒置原则的本质就是通过抽象(接口或抽象类)使个各类或模块的实现彼此独立,互不影响,实现模块间的松耦合。


(2) 举例

问题描述:类A直接依赖类B,假如要将类A改为依赖类C,则必须通过修改类A的代码来达成。这种场景下,类A一般是高层模块,负责复杂的业务逻辑;类B和类C是低层模块,负责基本的原子操作;假如修改类A,会给程序带来不必要的风险。

解决方案:将类A修改为依赖接口interface,类B和类C各自实现接口interface,类A通过接口interface间接与类B或者类C发生联系,则会大大降低修改类A的几率。


(3) 好处

依赖倒置的好处在小型项目中很难体现出来。但在大中型项目中可以减少需求变化引起的工作量。使并行开发更友好。

里氏替换原则

核心思想:在使用基类的的地方可以任意使用其子类,能保证子类完美替换基类。通俗的说,就是只要父类能出现的地方子类就能出现。反之,父类则未必能胜任。

好处:增强程序的健壮性,即使增加了子类,原有的子类还可以继续运行。

需注意:如果子类不能完整地实现父类的方法,或者父类的某些方法在子类中已经发生“畸变”,则建议断开父子继承关系 采用依赖、聚合、组合等关系代替继承。

迪米特法则

Law of Demeter,简称LoD

核心思想:类间解耦。

通俗来讲:一个类对自己依赖的类知道的越少越好。简而言之:高内聚,低耦合。

开放封闭原则

Open Close Principle,简称OCP

核心思想:尽量通过扩展软件实体来解决需求变化,而不是通过修改已有的代码来完成变化。

通俗来讲: 一个软件产品在生命周期内,都会发生变化,既然变化是一个既定的事实,我们就应该在设计的时候尽量适应这些变化,以提高项目的稳定性和灵活性。

设计模式分类

23种设计模式——创建型设计模式(5种)

设计模式简述

设计模式是在软件开发过程中针对常见问题和场景提供的一种解决方案。它们是经过多年实践和总结得出的最佳实践,可以帮助开发人员解决复杂的设计问题,提高代码的可重用性、可维护性和灵活性。


常见有23种设计模式,每种设计模式都有特定的应用场景和优缺点,开发人员应根据实际问题的需求来选择合适的设计模式。使用设计模式可以帮助开发人员写出更优雅、可维护和可扩展的代码,提高软件开发的效率和质量。然而,不应过度使用设计模式,应根据实际情况选择最合适的解决方案。

按模式目的分类

根据模式是用来完成什么样的工作来划分,这种方法可分为创建型模式、结构型模式、行为型模式3种。

(1) 创建型模式(Creational Patterns)

主要关注对象的创建过程,用于解决对象的实例化过程中可能存在的问题。

常见的创建型模式包括简单工厂模式、工厂方法模式、抽象工厂模式、建造者模式和单例模式等。


(2) 结构型模式(Structural Patterns)

主要关注对象之间的组合和关联关系,用于解决类和对象的组织方式和结构问题。

常见的结构型模式包括适配器模式、装饰者模式、代理模式、桥接模式和组合模式等。


(3) 行为型模式(Behavioral Patterns)

主要关注对象之间的通信和交互方式,用于解决对象之间的合作和协作问题。

常见的行为型模式包括观察者模式、命令模式、策略模式、模板方法模式和访问者模式等。

按作用对象分类

根据模式的主要用于类上还是主要用户对象上来分,这种方式可分为类模式和对象模式两种。

(1) 类模式

用于处理类与子类之间的关系,这些关系通过继承来建立,是静态的,在编译时便确定下来了。如,工厂方法、(类)适配器、模板方法、解释器等4种类模式。


(2) 对象模式

用户处理对象之间关系的,这些关系可以通过组合或聚合来实现,在运行时刻是可以变化的,更具动态性。

设计模式简介

创建型模式(Creational Patterns)

模式 说明
工厂方法模式
Factory Method Pattern
定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类中。
抽象工厂模式
Abstract Factory Pattern
提供一个创建一系列相关或者相互依赖的接口,而无需指定它们具体的类。
建造者模式
Builder Pattern
将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
原型模式
Prototype Pattern
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
单例模式
Singleton Pattern
保证一个类仅有一个实例,并提供一个访问它的全局访问点。

结构型模式(Structural Patterns)

模式 说明
适配器模式
Adapter Pattern
将一个类的接口转换成客户希望的另外一个接口。使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
桥接模式
Bridge Pattern
将抽象部分与实际部分分离,使它们都可以独立的变化。
组合模式
Composite Pattern
将对象组合成树形结构以表示“部分–整体”的层次结构。使得用户对单个对象和组合对象的使用具有一致性。
装饰者模式
Decorator Pattern
动态的给一个对象添加一些额外的职责。就增加功能来说,此模式比生成子类更为灵活。
外观模式
Facade Pattern
为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
享元模式
Flyweight Pattern
以共享的方式高效的支持大量的细粒度的对象。
代理模式
Proxy Pattern
为其他对象提供一种代理以控制对这个对象的访问。

行为型模式(Behavioral Patterns)

模式 说明
策略模式
Strategy Pattern
定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的改变不会影响算法的客户。
模版模式
Template Pattern
定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特点步骤。
观察者模式
Observer Pattern
多个对象间存在一对多的关系,当一个对象发生改变时,把这种改变通知给其他多个对象,从而影响其它对象的行为。
状态模式
State Pattern
允许一个对象在其内部状态发生改变时改变其行为能力。
备忘录模式
Memento Pattern
在不破坏封装性的前提下,获取并保存一个对象的内部状态,以便以后回复它。
访问者模式
Visitor Pattern
在不改变集合元素的前提下,为一个集合中的每个元素提供多种访问方式,即每个元素有多个访问者对象。
职责链模式
Chain of Responsibility Pattern
在该模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求,这使得系统可以在不影响客户端的情况下动态地重新组织链和分配责任。
命令模式
Command Pattern
将一个请求封装为一个对象,从而使你可用不同的请求对客户端进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
解释器模式
Interpreter Pattern
描述了如何为简单的语言定义一个语法,如何在该语言中表示一个句子,以及如何解释这些句子。
迭代器模式
Iterator Pattern
提供了一种方法顺序来访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。
中介者模式
Mediator Pattern
定义一个中介对象来封装系列对象之间的交互。终结者使各个对象不需要显示的相互调用 ,从而使其耦合性松散,而且可以独立的改变他们之间的交互。
备忘录模式
Memento Pattern
在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。