Java设计模式学习笔记

Java设计模式学习笔记

面向对象概念

方法 属性 关系 集合
面向对象特点

  1. 封装性: 将变量 方法 组合为一个实体 并控制 变量或方法的访问权限
  2. 继承性: 从父类派生子类 子类具有父类的属性与方法 并能扩展新的能力
  3. 多态性:允许同一个接口被不同对象实现
类与类之间的关系(耦合度从低到高但是5=6)
  1. 依赖关系 人用手机打电话
  2. 关联关系 老师与学生
  3. 聚合关系 学校与老师
  4. 组合关系 头与嘴巴
  5. 泛化关系 子类与父类
  6. 实现关系 实现类与接口

面向对象设计原则

开闭原则
开闭原则定义

软件实体应当对扩展开放对修改关闭(Software entities should be open to extensions and closed to modifications)

开闭原则实现方法
  1. 抽象约束
  2. 封装变化
    即: 通过接口与抽象类为软件定义一个相对稳定的抽象层 而将相同的可变因素封装在相同的具体实现类中
里氏替换原则(Liskov Substitution Principle)(对开闭原则的补充)

继承必须确保超类所拥有的性质在子类中仍然成立(Inheritance should ensure that any property proved about supe pe objects also holds
for subtype objects)

里氏替换原则实现方法

子类继承父类时候 除了添加新的方法完成新增功能外 尽量不重写父类的方法

依赖倒置原则(实现开闭原则的重要途经之一)

高层模块不应该依赖底层模块 两者都应该依赖其抽象
抽象不应该依赖细节 细节应该依赖抽象(High level modules should not depend upon low level modules. Both should depend upon abstractions. Abstractions should not pend
upon details. Details should depend upon abstractions)
核心思想为 面向接口编程 不要面向实现编程

依赖倒置原则事项方法
  1. 每个类尽量提供接口或抽象类 或者两者都具备
  2. 变量的声明类型 尽量是接口或者是抽象类
  3. 任何类都不应该从具体类派生
  4. 使用继承时尽量遵循里氏替换原则
单一职责原则

一个类应该有且只有同一个引起它变化的原因 否则 类应该被拆分(There should never be more than on reason for a class to change)

单一职责实现方法

发现类不同职责 并将其分离 在封装到不同的类或者模块中
单一职责同样也适用于方法
一个方法应该尽可能做好一件事情

接口隔离原则

客户端不应该被迫依赖于它不使用的方法(Clients should not be forced to depend on
methods they do not use)
一个类对另一个类的依赖应该建立在最小的接口上(Clients should not be forced to depend on
methods they do not use)

接口隔离原则实现方法
  1. 接口尽量小 但是要有限度 一个接口只服务于一个子模块或者业务逻辑
  2. 为依赖接口的类定制服务。只提供调用者需要的方法,屏蔽不需要的方法。
  3. 了解环境,拒绝盲从
  4. 提高内聚,减少对外交互。使接口用最少的方法去完成最多的事情。
最少知识法则

如果两个软件实体无须直接通信 那么就不应当发生直接的相互调用 可以通过第三方转发该调用(Talk only to your immediate
friends and not to strangers)

最少知识法则实现方法
  • 依赖者只依赖它应该依赖的对象
  • 被依赖者只暴露应该暴露的方法
  1. 在类的划分上,应该创建弱耦合的类
  2. 在类的结构设计上尽 降低类成员的访问权限
  3. 在类的设计上,优先考虑将一个类设置成不变类
  4. 在对其他类的引用上,将引用其他对象的次数降到最低
  5. 不暴露类的属性成员 而应该提供相应的访问器
  6. 谨慎使用序列化功能

创建型模式

将对象的创建与使用分离

  • 单例模式:某个类只能生成一个实例,该类提供了一个全局访
    问点供外部获取该实例,其拓展是有限多例模式。
  • 原型模式: 某个类只能生成一个实例,该类提供了一个全局访
    问点供外部获取该实例,其拓展是有限多例模式。
  • 工厂方法: 定义一个用于创建产品的接口 由子类决定生产什么产品
  • 抽象工厂: 提供一个创建产品族的接口 其每个子类可以生产一系列相关的产品
  • 建造者: 将一个复杂的对象分解成多个相对简单的部分 然后根据不同需要分别创建他们 最后构建成该复杂对象

单例模式

节省内存资源 保证数据内容一致性 只能创建一个实例

单例模式特点
  1. 单例类只有一个实例对象
  2. 该单例对象必须由单例类自定创建
  3. 单例类对外提供一个访问该单例的全局访问点
单例模式结构
  1. 单例类:包含一个实例且能自行创建这个实例的类
  2. 访问类:使用单例类
单例模式实现
懒汉式单例

加载时没有生成单例 当第一次调用getInstance方法时才去创建这个单例
多线程时候 需要volitate 保证可见性与有序性 添加 synchronized 保证原子性

饿汉单例模式

类属性直接创建实例

单例模式使用场景
  • 类只要求一个对象时
  • 对象需要被共享
  • 类需要频繁实例化 且对象又频繁销毁

原型模式

用一个已经创建的实例作为原型 通过赋值该原型对象来创建一个和原型相同或者相似的新对象

原型模式结构
  1. 抽象原型类: 规定了具体原型对象必须实现的接口
  2. 具体原型类: 实现抽象原型类的clone()方法 它是可被复制的对象
  3. 访问类: 使用具体原型类中的clone()方法来复制新的对象
原型模式的实现

JAVA实现Cloneable接口就可以实现对象的浅克隆

原型模式的应用场景
  1. 对象之间相同或相似 即只是个别几个属性不同的时候
  2. 对象的创建过程比较麻烦 但是复制比较简单的时候

工厂方法

定义一个创建产品对象的工厂接口 将产品对象的实际创建工作推迟到具体工厂类中 被创建的对象称为产品 创建产品的对象称为工厂

工厂方法结构
  1. 抽象工厂:提供了创建产品的接口 调用者通过它访问具体工厂的工厂方法来创建产品
  2. 具体工厂: 主要是实现抽象工厂中的抽象方法 完成具体产品的创建
  3. 抽象产品: 定义了产品的规范 描述了产品的主要特性和功能
  4. 具体产品: 实现抽象产品角色所定义的接口 由具体工厂来创建 它同具体工厂之间一一对应
工厂模式应用场景
  1. 客户只知道创建产品的工厂名 不知道具体的产品名
  2. 创建对象的任务由多个具体子工厂中的某一个完成 而抽象工厂只提供创建产品的接口
  3. 客户不关心创建产品的细节 只关心产品的品牌

建造者模式

将一个复杂对象的构造与它的表示分离 使同样的构建过程可以创建不同的表示

建造者模式结构
  1. 产品角色: 它是包含多个组成部件的复杂对象 由建造者来创建其各个组成部件
  2. 抽象建造者: 它是一个包含创建产品各个子部件的抽象方法接口 通常还包含一个返回复杂产品的方法
  3. 具体建造者: 实现builer接口 完成复杂产品的各个部件的具体创建方法
  4. 指挥者:它调用建造者对象中的部件构造与装配方法完成复杂对象的创建 在指挥者中不涉及具体的产品的信息
建造者模式的应用场景
  1. 创建的对象较为复杂 由多个部件构成 各部件面临着复杂的变化 但构件间的建造顺序是稳定的
  2. 创建复杂对象的算法独立于该对象的组成部分以及它们的装配方式 即产品的构建过程和最终表示是独立的

结构型模式

代理模式

由于某些原因需要给某对象提供一个代理以控制对该对象的访问 这时 访问对象不适合或者不能直接引用目标对象 带对象作为访问对象和目标对象之间的中介

代理模式的结构
  1. 抽象主题类:通过接口或抽象类声明真实主题和代理对象实现的业务方法
  2. 真实主题类: 实现了抽象主题中的具体业务
  3. 代理类:提供了与真实主题相同的接口 其内部含有对真实主题的引用 它可以访问 控制或扩展真实主题的功能

适配器模式

将一个类的接口转换成客户希望的另外一个接口 使得原本由于接口不兼容不能一起工作的那些类能一起工作

适配器模式的结构
  1. 目标接口: 当前系统业务所期待的接口 它可以是抽象类或接口
  2. 适配者类: 它是被访问和适配的现存组件库中的组件接口
  3. 适配器类: 它是一个转换器 通过继承或引用对象 把适配者接口转换成目标接口 让用户按目标接口访问适配者
适配者模式的应用场景
  1. 以前开发的系统存在满足新系统功能需求的类 但其接口同新系统的接口不一致
  2. 使用第三方提供的组件 但组件接口定义和自己要求的接口定义不同

桥接模式

将抽象与实现分离 使他们可以独立变化

桥接模式的结构
  1. 抽象化角色: 定义抽象类 并包含一个对实现化对象的引用
  2. 扩展抽象化角色: 抽象化角色的子类 实现父类中的业务方法 并通过组合关系调用实现化角色中的业务方法
  3. 实现化角色:定义实现化角色的接口 供扩展抽象化角色调用
  4. 具体实现化角色: 给出实现化角色接口的具体实现
桥接模式的应用场景
  1. 当一个类存在于两个独立变化的维度 且这两个维度都需要进行扩展时
  2. 当一个系统不希望使用继承或因为多层次继承导致系统的个数急剧增加时
  3. 当一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性时

装饰模式

指在不改变现有对象结构的情况下 动态地给该对象增加额外功能的模式

抽象模式的结构
  1. 抽象构件: 顶一个一个抽象接口以规范准备接收附加责任的对象
  2. 具体构件: 实现抽象构件
  3. 抽象装饰: 继承抽象构件 并包含具体构建的实例
  4. 具体装饰: 实现抽象装饰的相关方法
抽象模式的应用场景
  1. 当需要给一个现有类附加职责 而不能采用生成子类的方法进行扩充时
  2. 当需要通过对现有的一组基本功能进行排列组合 而产生非常多的功能时
  3. 当对象的功能要求可以动态地添加撤销时

外观模式

通过为多个复杂的子系统提供一个一致的接口 而使这些直筒更加容易被访问

外观模式结构
  1. 外观角色: 为多个子系统对外提供一个共同的接口
  2. 子系统角色: 实现系统的部分功能 客户可以通过外观角色访问它
  3. 客户角色: 通过一个外观橘色访问各个子系统的功能
外观模式的应用场景
  1. 对分层结构系统构建时 使用外观模式定义子系统中每层的入口点 可以简化子系统之间的依赖关系
  2. 当一个复杂系统的子系统很多时 外观模式可以为系统设计一个简单的接口供外界访问
  3. 当系统客户端与多个子系统之间存在很大联系时 引入外观模式可以将他们分离

享元模式

运用共享技术来有限地支持大量细粒度对象的复用

享元模式的结构
  1. 抽象享元角色: 是所有的具体类享元的基类 为具体享元规范需要实现的公共接口 非享元的外部状态以参数形式通过方法传入
  2. 具体享元角色: 实现抽象享元角色中所规定的接口
  3. 非享元角色: 是不可以共享的内部状态 它以参数的形式注入具体享元的相关方法中
  4. 享元工厂角色: 负责创建和管理享元角色
模式的应用场景
  1. 系统中存在大量或相似的对象 这些对象耗费大量的内存资源
  2. 大部分的对象可以按照内部状态进行分组 且可以将不同部分外部化
  3. 应当在有足够对的享元实例时才值得使用享元模式

组合模式

将对象组合成树状的层次结构的模式 用来表示部分-整体的关系 使用户对单个对象和组合对象具有一致的访问性

组合模式的结构
  1. 抽象构件角色: 为树叶构件及树枝构件声明公共家口 并实现他们的默认行为
  2. 树叶构件角色: 是组合中叶节点对象 它没有子节点 用于实现抽象构件角色中声明的公共接口
  3. 树枝构件角色: 是组合中的分支节点对象 它有子节点 实现了抽象构件角色中声明的接口 主要是存储和管理子部件

行为型设计模式

模板方法模式

定义一个操作中的算法骨架 而将算法一些步骤延迟的子类中 使子类可以不改变该算法结构的情况下重新定义该算法的特定步骤

模板模式的结构
  1. 抽象类: 负责给出一个算法的轮廓和骨架 它由一个模板方法和若干个基本方法构成
    1. 模板方法: 定义了算法的骨架 按照某种顺序调用其包含的基本方法
    2. 基本方法: 是整个算法中的一个步骤 包含以下几种类型
      • 抽象方法: 在抽象类中申明 由具体子类实现
      • 具体方法: 在抽象类中已经实现 在具体子类中继承或重写它
      • 钩子方法: 在抽象类中已经实现 包括用于判断逻辑方法和需要子类重写的空方法两种
  2. 具体子类: 实现抽象类中所定义的抽象方法和钩子方法 他们是一个顶级逻辑的一个组成步骤
模板方法的应用场景
  1. 算法的整体步骤很固定 但其中个别部分易变时
  2. 当多个子类存在公共的行为时 可以将其提取出来并集中到一个公共父类中
  3. 当需要控制子类的扩展时 模板方法只在特定的点调用钩子操作

策略模式

定义了一系列算法 并将每个算法封装起来 使他们可以相互替换 且算法的变化不会影响使用算法的用户

策略模式的结构
  1. 抽象策略类: 定义一个公共接口 各种不听的算法以不同的方式实现这个接口
  2. 具体策略类: 实现抽象策略定义接口 提供具体的算法实现
  3. 环境类: 持有一个策略类的引用 最终给客户端调用
策略模式的应用场景
  1. 一个系统需要动态地在几种算法中选择一种时,可将每个算法封装到策略类中。
  2. 一个类定义了多种行为 并且这些行为在这个类的操作中以多个条件语句的形式出现,可
    将每个条件分支移入它 各自的策略类中以代替这些条件语句。
  3. 系统中各算法彼此完全独立,且要求对客户隐藏具体算法的实现细节时。
  4. 系统要求使用算浊的客户不应该知道其操作的数据时,可使用策略模式来隐藏与算法相关
    的数据结构。
  5. 多个类只区别在表现行为不同,可以使用策略模式,在运行时动态选择具体要执行的行为。

命令模式

将一个请求封装为一个对象 使发出请求的责任和执行请求的责任分割开

命令模式的结构
  1. 抽象命令类角色: 声明执行命令的接口 拥有执行命令的抽象方法
  2. 具体命令角色: 是抽象命令类的具体实现类 拥有接收者对象 并通过调用接受者的功能来完成命令要执行的操作
  3. 实现者(接受者对象):执行命令功能的相关操作 是具体命令对象业务的真正实现者
  4. 调用者(请求者角色): 是请求的发送者 他通常拥有很多的命令对象 并通过访问命令对象来执行相关请求 它不直接访问接收者
命令模式的应用场景
  1. 当系统需要将请求调用者与请求接受者解耦时
  2. 当系统需要随机请求命令或经常增加或删除命令时
  3. 当系统需要执行一组操作时
  4. 当系统需要支持命令的撤销操作和恢复操作时

职责链模式

为避免请求发送者与多个请求处理者耦合在一起 将所有请求的处理者通过前一对象记住其下一个对象的引用而练成一条链

职责链模式的结构
  1. 抽象处理者: 定义一个处理请求的接口 包含抽象处理方法和一个后继连接
  2. 具体处理者角色: 实现抽象处理者的处理方法 判断能否处理本次请求 如果可以处理 则处理 不能处理则将该请求转给它的后继者
  3. 客户类角色: 创建处理链 并向链头的具体处理者独享提交请求 它不关心处理细节和请求传递过程
职责链模式的应用场景
  1. 有多个对象可以处理一个请求 那个对象处理该请求由运行时刻自动确定
  2. 可动态指定一组定向处理请求 或添加新的处理者
  3. 在不明确指定请求处理者的情况下 向多个处理者中的一个提交请求

状态模式

对有状态的对象 把复杂的判断逻辑提取到不同的状态对象中 允许状态对象在其内部状态发生改变时改变其行为

状态模式的结构
  1. 环境角色: 定义了客户感兴趣的接口 维护一个当前状态 并将与状态相关的操作委托给当前的状态对象来处理
  2. 抽象状态角色: 定义一个接口 用以封装环境对象中的特定状态锁对应的行为
  3. 具体状态角色: 实现抽象状态所对应的行为
状态模式的应用场景
  1. 当一个对象的行为取决于它的状态 并且它必须在运行时根据状态改变它的行为时 就可以考虑使用状态模式
  2. 一个操作中含有庞大的分支结构 并且这些分支决定于对象的状态时

观察者模式

多个对象间存在一对多的依赖关系 当一个对象的状态发生改变时 所有依赖于它的对象都得到通知 并自动更新

观察者模式的结构
  1. 抽象主题角色: 提供了一个用于保存观察者对象的聚集类和增加 删除观察者对象的方法 以及通知所有观察者的方法
  2. 具体主题角色: 它实现抽象目标中的通知地方法 当具体主题的内部状态发生改变时 通知所有注册过的观察者对象
  3. 抽象观察者角色: 抽象类或者接口 包含了一个更新自己的抽象方法 当接到具体主题的更改通知被调用
  4. 具体观察者角色: 实现抽象观察者中定义抽象方法 以便在得到目标的更改通知时更新自身的状态
观察者模式的应用场景
  1. 对象间存在一对多关系 一个对象的状态发生改变会影响其他对象
  2. 当一个抽象模型有两个方面 其中一个方面依赖于灵异方面时 可将这二者封装在独立的对象中 以使他们可以各自独立地改变和复用

中介者模式

定义一个中介对象来封装一些列对象之间的交互 使原有对象之间的耦合松散 且可以独立地改变他们之间的交互

中介者模式的结构
  1. 抽象中介者角色: 中介者的接口 提供了同事对象注册与转发同事对象信息的抽象方法
  2. 具体中介者角色: 实现中介者接口 定义一个List来管理同事对象 协调各个同事角色之间的交互关系
  3. 抽象同事类角色: 定义同事类的接口 保存中介者对象 提供同事对象交互的抽象方法 实现所有相互影响的同事类的功能
  4. 具体同事类角色: 是抽象同事类的实现者 当需要与其他同事对象交互时 有中介者对象负责后续的交互
中介者模式的应用场景
  1. 当对象之间存在复杂的网状结构关系而导致依赖关系混乱且难以复用时
  2. 当想创建一个运行于多个类之间的对象 又不想生成新的子类时

迭代器模式

提供一个对象来顺序访问聚合对象中的一系列数据 而不暴露聚合对象的内部表示

迭代器模式结构
  1. 抽象聚合 定义存储添加删除以及返回迭代器对象的方法
  2. 具体聚合 实现抽象聚合接口
  3. 抽象迭代器 定义访问遍历聚合对象的接口
  4. 具体迭代器 实现抽象迭代器
迭代器模式应用场景
  1. 当需要对聚合对象提供多种遍历方式时
  2. 当需要对不同的聚合对象提供统一的访问接口时
  3. 当访问一个对象无须暴露其内部表示时

访问者模式

将作用于某种数据结构中的各元素操作分离出来封装成独立的类 使其在不改变数据结构前提下 可以添加作用于这些元素的新操作 为数据结构中的每个元素提供不同的访问方式

访问者模式的结构
  1. 抽象访问者角色 定义了访问具体元素的接口
  2. 具体访问者角色 实现了抽象访问者中 声明各个访问元素的操作
  3. 抽象元素角色 声明了一个接受accept()接口 被访问者对象作为此接口的参数
  4. 具体元素角色 实现抽象元素角色
  5. 对象结构角色 包含元素角色的接口
访问者模式应用场景
  1. 对象结构相对稳定 但操作算法经常变化的场景
  2. 对象结构中需要提供多种不同且不相关的操作 而且要避免操作变化影响对象结构的场景
  3. 对象结构中包含很多不同类型的元素 需要按照类型进行不同操作的场景

备忘录模式

在不破坏封装的前提下 捕获一个对象的内部状态 并在对象之外保存这个状态 以便以后需要这个状态时恢复这个状态

备忘录模式结构
  1. 发起人角色 提供当前内部状态的信息 提供创建备忘录 恢复备忘录数据的功能 它可以访问备忘录里的所有信息
  2. 备忘录角色 负责存储发起人角色的内部状态 并在需要的时候 提供这些内部状态给发起人
  3. 管理者角色 对备忘录角色进行保存和获取功能 但是不能对备忘录角色进行修改与访问
备忘录模式应用场景
  1. 需要保存与恢复数据的场景
  2. 提供一个可回滚操作的场景

解释器模式

给分析对象定义一个语言 并定义该语言的文法表示 在设计一个解析器来解释语言中的句子

解释器模式的结构
  1. 抽象表达式角色: 定义解释器的接口 约定解释器的解释操作 主要包含解释方法
  2. 终结符表达式角色: 是抽象表达式的子类 用来实现文法中与中介符相关的操作
  3. 非终结符表达式: 也是抽象表达式的子类 用来实现文法中与非终结符相关的操作
  4. 环境角色: 通常包含哥哥哥解释器需要的数据或是公共的功能 一般用来传递被所有解释器共享的数据 后面解释器可以从这里获取这些值
  5. 客户端: 主要任务是将需要分析的句子或表达式转换成使用解释器对象描述的抽象语法树 然后调用解释器的解释方法
解释器模式应用场景
  1. 语言的文法比较简单 且执行效率不是关键问题时
  2. 当问题重复出现 且可以用一种 简单的语言来进行表达时
  3. 当一个语言需要解释执行 并且语言中的句子可以表示为一个抽象语法树的时候
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值