• 第04篇_设计模式

    第01章_设计模式

    第一节 设计模式概述

    1. 设计模式是什么?

    设计模式是软件开发中的最佳实践,帮助开发者在面对复杂设计问题时提供有效的解决方案。

     

    2. 面向对象设计原则

    面向对象设计原则为支持可维护性复用而诞生,这些原则蕴含在很多设计模式中,它们是从许多设计方案中总结出的指导性原则。

    image-20241125164240619

     

    3. 设计模式的分类

    1) 创建型模式

    image-20241125164044746

     

    2) 结构型模式

    image-20241125164119204

     

    3) 行为型模式

    image-20241125164139799

     

     

    第二节 创建型模式(Creational Patterns)

    创建型模式关注于对象的创建,提供了更灵活的对象创建方式。

     

    1. 单例模式(Singleton Pattern)

    单例模式指一个类只有一个实例,并提供一个全局访问点。下面是 Java 中的一些实现方式:

     

    1) 饿汉式(静态常量)【可用】

    优点:这种写法比较简单,就是在类装载的时候就完成实例化,避免了线程同步问题。

    缺点:在类装载的时候就完成实例化,没有达到 Lazy Loading 的效果。如果从始至终从未使用过这个实例,则会造成内存的浪费。

     

    2) 饿汉式(静态代码块)【可用】

    这种方式和上面的方式类似,只不过将类实例化的过程放在了静态代码块中,也是在类装载的时候执行静态代码块中的代码,初始化类的实例。优缺点和上面一样。

     

    3) 懒汉式(线程不安全)【不可用】

    这种写法起到了 Lazy Loading 的效果,但是只能在单线程下使用。如果在多线程下,一个线程进入了 if (instance == null) 判断语句块,还未来得及往下执行,另一个线程也通过了这个判断语句,这时便会产生多个实例。所以在多线程环境下不可使用这种方式。

     

    4) 懒汉式(线程安全,同步方法)【不推荐用】

    解决上面线程不安全问题的方式是对 getInstance() 方法进行同步。但这种方式效率太低,每个线程在想获得类的实例时,执行getInstance() 方法都要进行同步。其实这个方法只需执行一次实例化代码,后面直接 return 实例化对象即可。

     

    5) 懒汉式(线程安全,同步代码块)【不可用】

    这种方式尝试使用同步代码块来提高效率,但仍无法保证线程安全。如果一个线程进入了 if (instance == null) 判断语句块,还未来得及往下执行,另一个线程也通过了这个判断语句,这时便会产生多个实例。

     

    6) 双重检查【推荐使用】

    Double-Check 概念对于多线程开发者来说不会陌生,进行了两次 if (instance == null) 检查,这样就可以保证线程安全。实例化代码只需执行一次,后面再次访问时,判断 if (instance == null),直接 return 实例化对象。

    优点:线程安全;延迟加载;效率较高。

     

    7) 静态内部类【推荐使用】

    这种方式与饿汉式方式类似,都是采用类装载机制来保证实例化时只有一个线程。但不同的是,饿汉式在类装载时就实例化,没有 Lazy-Loading 效果,而静态内部类方式在需要实例化时才装载静态内部类,从而实例化 Singleton。类的静态属性只会在第一次加载类时初始化,所以这里JVM帮助保证了线程的安全性。

    优点:避免了线程不安全,延迟加载,效率高。

     

    8) 单元素枚举【推荐使用】

    创建枚举默认就是线程安全的,不需要担心 double checked locking,并且还能防止反序列化导致重新创建新的对象。枚举让JVM保证线程安全和单一实例问题,是 JDK1.5 版本后最适合用于创建单例设计模式的方法,是唯一一种不会被反射破坏单例状态的模式。

     

    2. 原型模式(Prototype Pattern)

    定义:指通过复制现有的实例来创建新实例,而不是通过构造函数。

    原理:实现 Cloneable 接口并重写 clone() 方法来复制对象。

    优点

     

    3. 建造者模式(Builder Pattern)

    定义:使用多个简单的对象一步一步构建一个复杂的对象。

    原理:定义一个建造者接口和具体建造者类,通过建造者类来创建复杂对象。

    优点

     

    4. 简单工厂模式

    定义:通过一个静态方法,根据传入的参数,返回不同类型的对象。

    优点:客户端不需要知道具体产品类的类名,只需要知道一个参数即可创建产品实例,降低了客户端与具体产品类的耦合。

    缺点

    使用场景

     

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

    定义:定义一个创建对象的接口,但由子类决定实例化哪个类。

    原理:将对象的创建逻辑放在子类中,而不是在客户端代码中。

    优点:

    缺点:

    使用场景:

     

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

    定义:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

    原理:通过定义多个工厂接口,每个接口负责创建一组相关的对象。

    优点:

    缺点:

    使用场景:

     

     

    第三节 结构型模式(Structural Patterns)

    结构型模式关注如何将类或对象组合成更大的结构,以便更好地实现功能。

     

    1. 适配器模式(Adapter Pattern)

    定义:将一个类的接口转换成客户希望的另一个接口。适配器模式使得原本接口不兼容的类可以合作。

    原理:通过引入一个适配器类,将目标接口转换为适配者接口。

    优点:

     

    2. 桥接模式(Bridge Pattern)

    定义:将抽象部分与实现部分分离,使它们可以独立地变化。

    原理:通过定义抽象类和实现类,将它们的变化解耦。

    优点:

     

    3. 组合模式(Composite Pattern)

    定义:将对象组合成树形结构以表示部分-整体层次结构,使得客户端对单个对象和组合对象的使用具有一致性。

    原理:通过定义一个组件接口,将叶子节点和容器节点统一处理。

    优点:

     

    4. 装饰器模式(Decorator Pattern)

    定义:动态地给一个对象添加一些额外的职责。装饰器模式提供了比继承更灵活的扩展功能的方式。

    原理:通过定义装饰器类来扩展被装饰对象的功能。

    优点:

     

    5. 外观模式(Facade Pattern)

    定义:为子系统中的一组接口提供一个一致的界面,使得子系统更容易使用。

    原理:通过定义一个外观类来封装子系统的复杂性,提供简化的接口。

    优点:

     

    6. 享元模式(Flyweight Pattern)

    定义:运用共享技术有效地支持大量细粒度的对象。

    原理:通过将对象的共享部分与独享部分分开,将共享部分提取出来。

    优点:

     

    7. 代理模式(Proxy Pattern)

    定义:为其他对象提供一种代理以控制对这个对象的访问。

    原理:通过定义代理类来控制对真实对象的访问。

    优点:

    分类:

     

    1) 静态代理

     

    2) JDK动态代理

     

    3) CGLIB动态代理

     

     

    第四节 行为型模式(Behavioral Patterns)

    行为型模式关注对象之间的沟通和职责分配

     

    1. 责任链模式(Chain of Responsibility Pattern)

    定义:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。

    原理:通过定义处理请求的链,并逐步将请求传递给链中的各个对象,直到找到合适的处理者。

    优点:

     

    2. 命令模式(Command Pattern)

    定义:将请求封装成一个对象,从而使你能够用不同的请求对客户进行参数化、队列化请求、以及支持可撤销操作。

    原理:通过定义命令接口和具体命令类,将请求封装为对象,并将其传递给调用者。

    优点:

     

    3. 迭代器模式(Iterator Pattern)

    定义:提供一种方法访问一个容器对象中各个元素,而又不暴露该对象的内部表示。

    原理:通过定义迭代器接口和具体迭代器类来遍历集合对象中的元素。

    优点:

     

    4. 中介者模式(Mediator Pattern)

    定义:定义一个对象来封装一组对象之间的交互,使得对象之间的耦合松散,从而使得它们可以独立地改变。

    原理:通过定义中介者接口和具体中介者类来协调对象之间的交互。

    优点:

     

    5. 备忘录模式(Memento Pattern)

    定义:在不暴露对象内部状态的情况下,捕获一个对象的内部状态,并在该对象外部保存这个状态。可以在以后将对象恢复到保存的状态。

    原理:通过定义备忘录类来保存对象的状态,并通过发起人类和恢复者类来实现状态的恢复。

    优点:

     

    6. 解释器模式(Interpreter Pattern)

    定义:给定一个语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。

    原理:通过定义解释器类和表达式类,将文法规则和解释逻辑分开。

    优点:

     

    7. 状态模式(State Pattern)

    定义:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。

    原理:通过定义状态接口和具体状态类,将对象的状态和行为分开,使得状态改变时可以改变行为。

    优点:

     

    8. 策略模式(Strategy Pattern)

    定义:定义一系列算法,将每一个算法封装起来,并使它们可以相互替换。策略模式让算法独立于使用它的客户而独立变化。

    原理:通过定义策略接口和具体策略类,将算法封装为对象,并在运行时选择使用。

    优点:

     

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

    定义:定义一个操作中的算法的骨架,将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下重新定义算法中的某些步骤。

    原理:通过定义模板方法在父类中,并将一些步骤的实现延迟到子类中。

    优点:

     

    10. 访问者模式(Visitor Pattern)

    定义:表示一个作用于某对象结构中的各元素的操作,它可以在不改变元素类的前提下定义作用于这些元素的新操作。

    原理:通过定义访问者接口和具体访问者类,将操作和对象结构分离,使得可以在不改变对象结构的情况下增加新的操作。

    优点:

     

    11. 观察者模式(Observer Pattern)

    定义:定义对象之间的一对多依赖,使得当一个对象改变状态时,所有依赖于它的对象都得到通知并被自动更新。

    原理:通过定义观察者接口和被观察者类来实现一对多的通知机制。

    优点:

     

     

    第五节 UML图

    1. UML简介

    UML 是 Unified Model Language 的缩写,中文是统一建模语言,是由一整套图表组成的标准化建模语言。分类如下:

    img

     

    2. 类图(Class Diagram)

    类图是面向对象系统建模中最常用和最重要的图,是定义其它图的基础,主要用来表示接口以及它们之间的静态结构和关系

    在类图中,常见的有以下几种关系:

     

    1) 泛化/继承(Generalization)

    泛化关系是一种继承关系(is A),表示子类继承父类的所有特征和行为。

    img

     

    2) 实现(Realization)

    实现关系是一种类与接口的实现关系(is A),表示类是接口所有特征和行为的实现。

    img

     

    3) 组合(Composition)

    组合关系是一种整体部分的关系,且部分不能离开整体而单独存在。组合关系是关联关系的一种,是比聚合关系还要强的关系。

    img

    鸟是整体,翅膀是部分。鸟死了,翅膀也就不能飞了。所以是组合。

     

    4) 聚合(Aggregation)

    聚合关系是一种整体部分的关系(has A),但部分可以离开整体而单独存在。聚合关系是关联关系的一种,是较强的关联关系;

    img

    电脑有键盘才能输入信息,电脑是整体,键盘是部分,键盘也可以离开电脑,单纯的拿去敲,所以是聚合。

     

    5) 关联(Association)

    关联关系是一种拥有关系(has A),它使得一个类知道另一个类的属性和方法。

    img

    车是车,人是人,没有整体与部分的关系。

    6) 依赖(Dependency)

    依赖关系是一种使用关系(use A),即一个类的实现需要另一个类的协助。

    img

    老司机只管开车,车是谁的不重要,给什么车开什么车。

     

    3. 其它UML图

    1) 组件图

    img

    订单系统组件依赖于客户资源库和库存系统组件。中间的虚线箭头表示依赖关系。另外两个符号,表示组件连接器,一个提供接口,一个需要接口。

     

    2) 部署图

    img

    图中简单的表示,不同机器上面部署的不同软件。

     

    3) 对象图

    img

    图中就是描述的,某时间点 bat 这个公司有一个研发部,一个销售部,两个部门只有一个人iisheng

     

    4) 包图

    img

    5) 组合结构图

    img

    图中描述了Car是由车轴连接着的两个前面轮子、两个后面轮子,和引擎组合的。

     

    6) 轮廓图

    img

    图中我们定义了一个简易的EJB的概要图。Bean是从Component扩展来的。Entity BeanSession Bean继承了BeanEJB拥有RemoteHome接口,和JAR包。

     

    7) 用例图

    img

    用例图中包含以下三种关系:

     

    8) 活动图

    img

    图中简单描述了,从开始到登录到查看订单列表,或者登录失败直接结束。

     

    9) 状态图

    img

    图中描述了,门在其生命周期内所经历的状态。

     

    10) 序列图

    img

    图中展示的是支付宝条码支付场景的序列图。其中,loop是循环,alt是选择,序列图的其他关系这里就不介绍了。

     

    11) 通讯图/协作图

    img

    图中展示了一个线上书店的通讯图,方框和小人表示生命线,不同生命线之间可以传递消息,消息前面的数字可以表达序列顺序。

     

    12) 交互概览图

    img

    图中表示一个调度系统的交互概览图,跟活动图很像。其中sd的框代表具体的交互流程,ref框代表使用交互。

     

    13) 时序图

    img

    图中展示了老年痴呆病人随着时间的变化病情的变化。