原创

设计模式详解——设计模式初识


一、什么是设计模式

1、概念

设计模式:是指在软件开发中,经过验证的,用于解决在特定环境下、重复出现的、特定问题解决方案

我们从以上标粗的词语中理解一下设计模式的概念

  • 软件开发

    宏观来说,设计模式遍布各行各业,包括IT、机械、建筑、医疗等行业。由于博主是程序员,所以本文介绍的设计模式主要指的是软件开发过程中的设计模式。

  • 解决方案

    首先申明一下,设计模式是一个解决方案,通俗地来说,就是解决问题的方法。当时反过来说解决方案就是一个设计模式是不正确的,因为解决方案需要满足特定的条件才能算设计模式,且听我下面慢慢分析。

  • 经过验证

    很好理解,作为一个解决方案,本身必须是靠谱的,即是经过验证可行的方案。

  • 特定环境

    在现实案例中,往往情况是非常复杂的。具体情况具体分析,即使问题相同,在不同的环境下,解决方法往往存在较大的差异。任何脱离特定场景下谈设计模式都是”耍流氓”

  • 重复出现

    作为程序员,一听到重复出现,相信大家都会考虑封装套用。设计模式就是在重复出现的特定场景下的一个优质的解决方案,这样下次遇到就可以直接使用已有的方案。

2、目的

  • 代码重用性
  • 可读性
  • 可扩展性
  • 可靠性
  • 灵活性
  • 高内聚、低耦合
  • 面向对象

3、背景

1995 年,艾瑞克·伽马(ErichGamma)理査德·海尔姆(Richard Helm)拉尔夫·约翰森(Ralph Johnson)约翰·威利斯迪斯(John Vlissides)4 位作者合作出版了《设计模式:可复用面向对象软件的基础》(Design Patterns: Elements of Reusable Object-Oriented Software)一书,在本教程中收录了 23 个设计模式,这是设计模式领域里程碑的事件,导致了软件设计模式的突破。这 4 位作者在软件开发领域里也以他们的“四人组”(Gang of Four,GoF)匿名著称。

本文介绍的设计模式即为上面四位大佬在书中总结的23种设计模式。

二、为什么要学习设计模式

  • 个人技术能力的提升

    设计模式基本都是前人的经验积累,绝大多数都是一些非常优秀的解决方案,一些设计模式甚至都是极具有典型性。我们学习设计模式,可以吸取前人的设计思想,学习前人解决问题的方案。站在巨人的肩膀,我们才能看到更高更远,个人的技术能力才能得到质的飞跃。

  • 避免重复造轮子

    前面说到设计模式是对经常出现的场景的解决方案。当我们遇到类似的场景可以直接借鉴前人总结的设计模式。一来我们自己思索未必能够想到这些优秀的设计模式,二来节省了大量的时间,让我们有更多的时间去优化、升华这些设计方案。

三、设计原则

在软件开发中,程序员应该尽量遵循一些基本原则来保证程序的健壮性、可扩展性、灵活性等。业内一般遵从以下七种设计原则:

1、单一职责原则

单一职责原则规定一个类应该有且仅有一个引起它变化的原因,否则类应该被拆分

通俗来说,就是一个类尽量只负责一项功能。例如类A负责功能P1P2,如果P1功能需要修改,就需要修改类A,由于P2功能也在类A中,就可能导致P2功能受到影响。

我们在开发中一个类尽量不要被赋予过多的功能,理想状态下一个类只负责一个功能,这样可以最大程度减少一个功能的修改对其余功能的影响。

2、接口隔离原则

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

一个类尽量不要依赖自己用不到的接口。例如接口I有方法fun1fun2,类A和类B都依赖这个接口,但是类A只使用到fun1,类B只使用到fun2,这样导致类A使用不到fun2方法,却被迫需要实现,类B同理。合理的方案是将接口I拆分成两个接口分别给类A和类B使用。

3、依赖倒置原则

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

核心思想:面向接口编程,不要面向实现编程。举个栗子,类A直接依赖类B,假如要将类A改为依赖类C,则必须通过修改类A的代码来达成。这种场景下,类A一般是高层模块,负责复杂的业务逻辑;类B和类C是低层模块,负责基本的原子操作;假如修改类A,会给程序带来不必要的风险。因此可以将类A修改为依赖接口I,类B和类C各自实现接口I,类A通过接口I间接与类B或者类C发生联系,则会大大降低修改类A的几率。

4、里式替换原则

继承必须确保超类所拥有的性质在子类中仍然成立

通俗来讲就是,子类可以扩展父类的功能,但不能改变父类原有的功能。即子类继承父类时,除添加新的方法完成新增功能外,尽量不要重写父类的方法

5、开闭原则

软件实体应当对扩展开放,对修改关闭

当应用的需求改变时,在不修改软件实体的源代码或者二进制代码的前提下,可以扩展模块的功能,使其满足新的需求。即我们的程序尽量满足一定的扩展灵活性。开闭原则是面向对象程序设计的终极目标,它使软件实体拥有一定的适应性和灵活性的同时具备稳定性和延续性

6、迪米特法则

如果两个软件实体无须直接通信,那么就不应当发生直接的相互调用,可以通过第三方转发该调用

目的就是降低类之间的耦合度,提高模块的相对独立性。即高内聚、低耦合

7、合成复用原则

在软件复用时,要尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现

在面向对象编程中,继承一定程度上会破坏封装,因为继承将基类的实现细节暴露给子类。同时如果基类发生变化,很可能会影响它的所有子类。因此在实际开发中尽量使用组合/聚合方式,减少联动影响

四、设计模式分类

设计模式一般有两种分类方法(下面只列出设计模式的名称,具体细节关注后续的文章吼)

1、按照模式的目的分

1.1、创建型模式
  • 单例模式
  • 工厂方法模式
  • 抽象工厂模式
  • 原型模式
  • 建造者模式
1.2、结构型模式
  • 代理模式
  • 适配器模式
  • 桥接模式
  • 装饰模式
  • 外观模式
  • 享元模式
  • 组合模式
  • 适配器模式
1.3、行为型模式
  • 策略模式
  • 模板方法模式
  • 命令模式
  • 职责链模式
  • 状态模式
  • 观察者模式
  • 中介者模式
  • 迭代器模式
  • 访问者模式
  • 备忘录模式

2、按照模式的作用范围分

2.1、类模式

工厂方法模式、适配器模式、模板方法模式、解释器模式

2.2、对象模式

除了上面四种的剩余部分

设计模式
Java
  • 作者:贤子磊
  • 发表时间:2021-05-18 03:33
  • 版权声明:自由转载-非商用-非衍生-保持署名
  • 评论

    您需要登录后才可以评论