软件23种设计模式(学习笔记)

基础概念

1. 类图

(1) 属性:

公开(+) 保护 (# ) 默认 ( ) 私有 (-)

修饰符 变量名: 类型 [= 默认值] // 例 + name:String, - age: int = 18

(2) 方法:

公开(+) 保护 (# ) 默认 ( ) 私有 (-)

修饰符 方法名: 返回值类型 // 例 + getName():String, + setName(String): void

2. 关联关系

注释:关联关系(全局变量),依赖关系(参数),一般关系(继承,实现)

2.1 关联关系

使一个类知道另一个类的属性和方法(继承父类属性,全局变量,局部变量,方法参数)

箭头指向属性类

(1) 单向关联

(2) 双向关联

(3) 自关联

2.2 聚合关系

目标对象作为变量可被不同对象引用

箭头指向引用者类

2.3 组合关系

目标对象作为变量在主类中存在,主类影响其生命周期

箭头指向引用者类

2.4 依赖关系

方法形参,局部变量

箭头指向局部变了或方法形参类

2.5 继承关系

箭头指向父类

2.6 实现关系

箭头指向接口

3. 设计原则

为保持软件(可维护性,复用性,扩展性,灵活性)

3.1 开闭原则

对扩展开放,对修改关闭

人话:有新需求时,做一个新的接口实现类(扩展),不改变已有接口的实现类(不修改)。

3.2 依赖倒转原则

开闭原则的实现,对接口编程不对实现编程

人话:调用者将变量定义成接口类型,当有新的接口实现类时,不需要改代码

3.3 里氏代换原则

对继承的约束,父类出现的地方一定可以用子类替代(子类只扩展父类,不重写父类已实现的方法)

人话:不允许子类重写父类方法,防止影响已有程序对调用父类方法的调用。

3.4 接口隔离原则

子类不应被迫实现不使用的方法

人话:子类用什么方法就实现什么接口,否则就将接口拆分成多个接口

3.5 迪米特法则

不相关的类不直接调用,通过中间类调用。一般与依赖倒转原则同时使用。

人话:(类1的方法)需要(类2方法)的返回值。不要在类1方法中(new 类2)调用方法,这样会使类1必须依赖类2。正确做法,在中间类中(new 类2)将返回值传给类1。

3.6 合成复用原则

尽量使用合成复用(组合,聚合关系),避免使用继承复用(继承关系)。

(1) 合成复用

优点:方便扩展,改修时,只需要更改变量的实现类。

(2) 继承复用

缺点:耦合度高,更改父类会影响所有子类

3.7 单一职责原则

注释:面向对象的设计原则

一. 创建型模式(5种)

1. 单例模式

序列化反序列化,与反射会破坏单例模式。

序列化类中,添加 public Object readResolve() { return 静态内部类.静态属性; } 保存单例模式

反射在私有构造器中抛出异常来禁止多个对象实例化。

1.1 饿汉式单例

加载即创建,不使用会浪费内存

(1) :静态变量,静态代码块

private static final 类 xx = new 类();

private static final 类; static { 类 = new 类}

(2) : 枚举类

定义枚举类

1.2 懒汉式单例

使用时才创建

(1) : 双重校验

私有静态volatile(解决jvm空指针),判null,锁,判null,返new

java 复制代码
private static volatile 属性; // 解决jvm空指针
public 属性 getXx() {
    if (属性 == null) {       // 解决每次都加锁的性能问题
      synchronized(类名.class) {
        if (属性==null) {
            属性 = new 属性();
        }
    }
  }
  return 属性;
}

// 1 公开方法,判断null,返回new对象(多线程同时访问,可能会new两次)

public 类 getXx() { if (属性 == null) { 属性 = new 属性(); } return 属性 }

// 2 公开synchronize方法,判断null,返回new对象(外部加锁影响性能)

public synchronized类 getXx() { if (属性 == null) { 属性 = new 属性(); } return 属性 }

(2) 私有静态内部类

利用jvm首次使用内部类属性才加载内部类的特性。

java 复制代码
public class 外部类 {
  private 外部类() {} //私有构造器
  private static class 内部类{
    private static final 属性 = new 属性();
  }
  public static 属性 getInstance() {
    return 内部类.属性;
  }

2. 工厂方法模式

优点:(工厂,实体)都满足开闭原则

缺点:创建对象繁琐,会导致类爆炸

简单工厂(不属于23种设计模式,是编码规范)

配置文件通过反射(全类名)解耦

3. 抽象工厂模式

优点:同类实体可通过一个工厂创建

缺点:添加产品需要更改所有工厂类

4. 原型模式

**(1) 浅拷贝:**实现Cloneable接口,重写clone方法

**(2) 深拷贝:**序列化,返序列化(实现序列化接口)

5. 建造者模式

优点:可解决构造器参数过多问题

二. 结构型模式(7种)

1.代理模式

1.1 静态代理

注释:(类)与类(属性类)实现同一个接口。A中套(B)。在类实现的方法中直接调用属性类的方法,可以在前后加处理逻辑。

1.2 动态代理

(1) Proxy代理接口

java 复制代码
接口 代理对象 = (强转) Proxy.newProxyInstance(
    参数1:当前类.class.getClassLoader(), 
    参数2:new Class[]{接口.calss},
    参数3:new InvocationHandler() ) {

        @Override
        public Object invoke(
            参数1:Object proxy,
            参数2:Method method, 接口方法
            参数3:Object[] args) {  // 方法参数

            method.getName();  // 可获取方法名
            ...处理
            method.invoke(参数对象);  //调用实际处理
            method.invoke(参数对象, args); // 调用有参数的实际处理

            // 有返回值就直接return method.invoke,或者retrun 其它

(2) Cglib代理类

2. 装饰者模式

注释:(类)与类(属性类)实现同一个接口。A聚合A1, A1聚合A2...一个接一个。

3. 组合模式

注释:(类)与类(属性类)实现同一个接口。A聚合List<A1>, A1聚合List<A2>,一个接多个。

4. 适配器模式(对象)

注释:(类)与类(属性类)实现不同接口。新建实现类A,使已有B类通过适配器能处理接口A

尽量使用(聚合组合)对象适配器模式,避免(继承)类适配器模式

5. 桥接模式

注释:有(A~Z)26个抽象实现类,和(0~9)10个接口实现。桥接模式,在这36个类的基础上,能够做出260种组合。避免了创建260个类。

6. 外观模式

注释:聚合了多个属性的类,将多个处理步骤封装,只对外公开一个方法。避免了使用者不了解多个方法执行顺序,导致的混乱。

7. 享元模式

注释:聚合了同一个类的多个实例对象(每个实例的属性不同)。背书(内部属性相同,外部属性不同)

三. 行为型模式(11种)

3.1 模版方法

注释:父类按顺序调用自己的方法(实例方法,抽象方法),执行流程固定时使用。

3.2 策略模式

注释:接口有多个实现类,调用不同实现类,实现不同效果(功能)。

3.3 迭代器

注释:内部类定义下标和数据,通过判断是否还有数据,根据下标拿到下一条数据。

3.4 观察者

注释:类内部发生变化时,循环调用观察者方法,实现对所有观察者的通知。

3.5 职责链

注释:依次让不同实现类处理,当中间类可处理或判断不可继续时,随时可能中止后续执行。

3.6 状态模式

注释:当状态变化,切换不同实现类,使方法执行时,执行的是当前状态下实现类的方法。

3.7 中介者

注释:迪米特法则的实现,中介类聚合了多个对象,对象通过父类可以调用中介类。

3.8 备忘录

注释:将属性做成新对象,存放起来。存接口类型,可防止外部获取到属性数据。

3.9 解释器

注释:实现类实现接口的方法时定义规则。(例:加法运算,两个值相加,或两个算术公式相加)

3.10 命令模式

注释:做成多个订单类,通过执行命令方法,循环执行具体处理。

3.11 访问者

注释:首先有List集合,将同1个对象人,循环传递给集合内的对象。不同的宠物对象将this自己,再传给得到的人对象。实现人对象的方法重载的调用。

作用:利用了方法的重载,避免List<接口>类型,循环时无法根据类型,直接调用接口2的重载方法。

相关推荐
近津薪荼2 小时前
递归专题5——快速幂
c++·学习·算法
短剑重铸之日2 小时前
《设计模式》第八篇:三大类型之创建型模式
java·后端·设计模式·创建型设计模式
Hill_HUIL2 小时前
学习日志24-OSPF基础
学习
野犬寒鸦3 小时前
从零起步学习并发编程 || 第四章:synchronized底层源码级讲解及项目实战应用案例
java·服务器·开发语言·jvm·后端·学习·面试
AI营销前沿3 小时前
AI市场分析平台榜单发布:原圈科技如何破解全球化增长难题?
笔记
£漫步 云端彡3 小时前
Golang学习历程【第十一篇 接口(interface)】
开发语言·学习·golang
三水不滴12 小时前
Redis 过期删除与内存淘汰机制
数据库·经验分享·redis·笔记·后端·缓存
wdfk_prog13 小时前
[Linux]学习笔记系列 -- [drivers][i2c]i2c-dev
linux·笔记·学习
土拨鼠烧电路13 小时前
笔记03:业务语言速成:“人、货、场”模型与IT系统全景图
笔记