【设计模式】设计模式原则

171 阅读6分钟

设计模式原则

这节为设计模式的前置知识。

单一职责原则:

一个类(大到模块,小到方法)承担的职责越多,复用可能性更小
因为当一个职责变化时, 可能会影响其它功能的运作,
因此需要将这些职责进行分离,封装在不同的类中,
将不同的变化原因封装在不同的类中

image.png

单一职责原则(定义作用及经典例子详解) – mikechen的互联网架构

符合单一职责原则的设计模式:

  1. 工厂模式(Factory Pattern):

将对象的创建(Factory)职责单独建立,每个工厂完成自己的工作,满足单一职责原则。

  1. 适配器模式(Adapter Pattern):

将目标类和需要适配的类(Adaptee类)的适配职责分离,使用适配器来进行接口适配,从而实现单一职责。

  1. 装饰者模式(Decorator Pattern):

通过将具体组件和装饰分离,每个装饰类为目标类添加特有的功能,从而实现单一职责。

  1. 代理模式(Proxy Pattern):

将代理职责和实际服务分离开来, 代理添加代理方法,实际服务完成自己的方法,也实现了单一职责。

  1. 模板方法模式(Template Method Pattern):

将算法框架和具体算法分离为模板方法和基本方法, 基本方法各自完成自己的任务,实现单一职责。

  1. 单例模式(Singleton Pattern):

仅负责实例化和返回单例对象,而不是管理单例生命周期, 从而实现单一职责。

开闭原则(主要实现可复用性):对扩展开放,修改关闭

  • 软件设计应该易于扩展,但不易于修改
  • 当软件需求有变化时,我们应该扩展软件的行为,而不是去修改原来的代码

比如我们使用抽象方法,这样有利于我们添加新的实现方法。

  1. 策略模式(Strategy Pattern)

定义多个具体策略类, 在运行时传入参数来判断需要哪种具体策略, 添加只用新建策略类, 符合开闭原则。

  1. 观察者模式(Observer Pattern)

观察者模式可以在不修改主题对象的情况下添加新的观察者,只需要addObserver即可,符合开闭原则。

  1. 工厂方法模式(Factory Method Pattern)

定义一个创建对象的接口, 工厂子类来创建类实例; 当需要新添产品时,直接新建一个具体工厂和具体产品即可, 符合开闭原则。

  1. 抽象工厂模式(Abstract Factory Pattern)

提供一个创建相关对象的接口, 具体逻辑由子类实现,符合开闭原则。

  1. 模板方法模式(Template Method Pattern)

定义一个操作中的算法的框架,将一些步骤延迟到子类中实现,当需要不同的实现时,新添加一个子类就行,符合开闭原则。

  1. 组合模式(Composite Pattern)

将对象组合成树形结构来表示"部分-整体"的层次结构,在不改变其他对象的情况下增添新子类型,满足开闭原则。

  1. 装饰器模式(Decorator Pattern)

动态地给一个对象添加一些额外的职责,在不修改对象自身情况下扩展其功能,符合开闭原则。

里氏代换原则:其实就是替换原则

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

意思就是父类对象一定可以指向子类对象,当我们不知道具体会创建哪种子类对象时,我们使用它的抽象类去指向即将要创建的子类对象,这样客户端使用时就不会觉得有区别。

依赖倒转原则: 高层模块不应该依赖低层模块,它们都应该依赖抽象。

高层模块不应该直接使用底层模块,而应该使用底层模块的抽象

这样高层模块和低层模块之间就不直接依赖了,而是通过中间的接口。

如果低层模块改变,只要继续实现接口,高层模块就不需要修改。

接口隔离原则:(客户端不应该依赖那些它不需要的接口)

  • 接口太大,需要将它分割为一些更细小的接口
  • 使用该接口的客户端仅需知道与之相关的方法即可
  • 每一个接口完成自己的功能,不能有不相关的功能

比如:

interface Animal {
    public void eat();
    public void travel();  
}

class Dog implements Animal {
    public void eat() { ... }    
    public void travel() { ... }     
}

这里 Dog 实现了 Animal 接口,但是它不需要 travel() 方法。这违背了接口隔离原则。

那应该怎么做呢?

将接口拆分为两个:

interface Pet {
    public void eat();  
    public void sleep();        
}

interface WorkAnimal {
    public void travel();         
}

合成复用原则(又称组合/聚合复用原则):

优先使用对象组合,而不是通过继承来达到目的。

合成复用原则就是在一个新的对象通过关联关系(聚合,组合)来使用一些已有的对象,使之成为新对象的一部分。\

尽量使用组合/聚合的方式替代继承关系

这是因为:

  • 继承可能会导致类等级结构过于复杂
  • 继承引入了强耦合,不利于代码扩展与维护

而使用组合/聚合:

  • 创建更松耦合的关系
  • 当一个类变化时,其他类不会受影响
  • 避免子类数量爆炸

分析:

  1. 继承复用: 实现简单,运行时不能发生改变,灵活性低。
  2. 组合复用:耦合度低,比较灵活,但可能会导致系统中的对象过多。

迪米特法则: (又称最小知识原则): 每一个软件单位都有最小的知识原则

可能会和单一职责搞混,单一职责是让类的功能尽可能少,迪米特法则是避免超出合作者的直接职责范围

比如: 我是老板,我只用叫经理办事,而不是直接去通知员工干事。

作用是:

  • 减少对象之间的间接关联和复杂交互
  • 仅与直接的合作者交互,避免超出合作者的直接职责范围
  • 减少耦合,提高可读性和可维护性

UML类图

大家要学习设计模式之前,必须先要看得懂类图,经常会用到,所以我给大家一个链接: