1 Star 0 Fork 0

little_lunatic/advance

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README

尚硅谷Java设计模式(图解+框架源码剖析)

23种设计模式源码地址

[TOC]

一、七大原则

1.单一职责原则

一个类只负责一项职责(并不是一个类只有一个方法)

image20211208112221440

2.接口隔离原则

客户端不依赖不需要的接口

image20211208135251334

改进后:image20211208135558964

3.依赖倒转原则

  • 高层模块不依赖底层模块,都应该依赖抽象(接口或抽象类)
  • 抽象不依赖细节,细节(实现类)依赖抽象
  • 依赖倒转的核心是面向接口编程

依赖关系传递的三种方式:接口传递、构造方法传递、setter方式传递

image20211208142040747

4.里氏替换原则

继承时,子类中尽量不要重写父类的方法

image20211208144925104


image20211208144813429

5.开闭原则【OCP】

对扩展开放,对修改关闭

image20211208150612090

image20211208151104907

6.迪米特法则

迪米特法则又叫最少知道原则,一个对象应该对其他对象保持最少的了解。

image20211208152642101

这里面的输出员工信息,放在自己的类里面对外提供public方法,不在另一个类重复这段代码,只需要调用该方法,即符合迪米特法则。

7.合成复用原则

尽量使用合成/聚合的方式,而不是使用继承

聚合:image20211208153537903

合成:image20211208153646985

设计原则核心:

  • 找出应用中可能需要变化的,独立出来,不要和不需要变化的代码混在一起
  • 针对接口编程,不针对实现编程
  • 松耦合

二、UML类图

image20211208154150268

三、设计模式(23种)

创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

amazing...

image20211208160011264

1 单例模式

1.1 饿汉式(静态常量)

//构造器私有化  
//静态常量本类对象  
//对外提供getInstance方法  

public class Singleton {
    private Singleton() {
    }

    private static final Singleton instance = new Singgleton();

    public static Singleton getInstance() {
        return instance;
    }
}  

advantage:

  • 写法简单
  • 类装载时完成了实例化,避免了线程同步的问题

disadvantage:

  • 类装载时就实例化,没有达到懒加载的效果
  • 如果不用这个实例,会造成内存浪费

1.2 懒汉式

1.2.1 线程不安全
public class Singleton {
    private Singleton() {
    }

    private static Singleton instance;

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}  

advantage:

  • 达到了懒加载的效果

disadvantage:

  • 线程不安全,多个线程同时进会创建多个实例
1.2.2 线程安全
public class Singleton {
    private Singleton() {
    }

    private static Singleton instance;

    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}  

advantage:

  • 解决了线程不安全问题

disadvantage:

  • 效率太低
1.2.3 DoubleCheck
public class Singleton {
    private Singleton() {
    }

    private static volatile Singleton instance;

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}  

advantage:

  • 解决了线程不安全问题
  • 实现懒加载
1.2.4 静态内部类
public class Singleton {
    private Singleton() {
    }

    private static class SingletonInstance {
        private static final Singleton INSTANCE = new Singleleton();
    }

    public static Singleton getInstance

    {
        return SingletonInstace.INSTANCE;
    }
}  
1.2.5 枚举
enum Singleton {
    INSTANCE;
}  

2 原型模式

克隆羊:传统模式

image20211214140702885

优点

  • 好理解,简单易操作

缺点

  • 创建新的对象时,需要重新获取原始对象的属性,创建的对象比较复杂时,效率较低
  • 不能动态获得对象运行时的状态,不够灵活

image20211214141157040

image20211214142532559

优点

  • 不用重新初始化对象,动态获得对象运行时的状态
  • 原始对象发生改变时,不需要修改源码,克隆对象也会改变。

缺点

  • 需要为类配置一个深克隆方法,对新类来说不是很难,但是对已有的类进行改造时,需要修改源码,违背了 OCP 原则

3 工厂模式

3.1.1 简单工厂(不算一种设计模式)

传统模式

image20211210134242572

传统方式新增 pizza 种类时,调用者的代码需要做大量的修改,违反了 OCP 原则。

简单工厂模式

image20211210165457339

工厂创建具体的 pizza ,调用者找 工厂就ok了。

//日历对象的创建,就使用到了简单工厂模式  
Calendar.getInstance();  

3.1.2 工厂方法模式

对象的实例化推迟到子类

image20211210191417000

3.2.3 抽象工厂模式

image20211214132054240

4 建造者模式

【也称为生成器模式】

盖房子:传统方式

image20211214153055006

优点

  • 好理解,简单易操作

缺点

  • 程序结构过于简单,没有设计缓存层对象,可扩展性和可维护性不好

解决方案

把产品和产品建造过程解耦 ==> 建造者模式

image20211214155303078

image20211214155324163

盖房子:建造者

image20211214160326839

//StringBuilder 就用到了建造者模式  
StringBuilder  

image20211215090941676

注意事项:

  • 客户端不必知道产品内部的组成细节,将产品与产品的创建解耦,使相同的创建过程可以创建不同的产品
  • 指挥者可以控制产品的创建过程
  • 新增具体建造者不需要修改源码,指挥者也可不用修改,直接在客户端调用,符合开闭原则

5 适配器模式

5.1 类适配器

基本介绍:Adapter 类通过继承 src 类,实现 dst 接口,完成 src-->dst 的适配

image20211216132903089

注意事项:

  1. 类适配器继承了 src 类,有了一定的局限性(java是单继承)。
  2. src 类的方法会暴露在 Adapter ,增加了使用成本
  3. 可以重写 src 类的方法,所以会更灵活

5.2 对象适配器(常用)

对象适配器和类适配器模式相同,只是 Adapter 不再继承 src 类,而是持有 src 类。

根据合成复用原则,尽量用关联关系代替继承。

image20211216145915636

5.3 接口适配器

image20211216151250889

接口中定义一堆方法,使用一个抽象类实现接口,并为该接口中的每一个方法提供一个默认的实现(空方法),那么该抽象类的子类可以有选择地覆盖父类的某些方法。

image20211216154240160

6 桥接模式

image20211217164100224

  • 新增一个样式,每个牌子的手机都要增加一个;新增一个手机,会在三个样式下都增加一个手机。增加了代码的维护成本。
  • 违反了单一职责原则。
  • 解决方案:桥接模式

桥接模式:结构型,基于类的最小设计原则。将抽象和实现分开,两个层次可以独立改变。

image20211217165737158

桥接模式解决手机问题:

image20211217170515657

桥为抽象类 Phone。

7 装饰者模式

符合 OCP 原则。

动态的将新功能附加到对象上,功能扩展更灵活。

8 组合模式

image20220105152227777

注意事项

  • 简化客户端操作
  • 具有较强的扩展性
  • 方便创建出复杂的层次结构
  • 需要遍历组织机构的,强烈推荐使用组合模式
  • 但是,要求较高的抽象性,如果节点和叶子节点有很多差异,则不适用组合模式

HashMap 中使用到了组合模式,component 为 AbstractMap。

image20220105164520352

9 外观模式

image20220105165532179

image20220105165716953

外观模式也叫 “过程模式” ,提供一个高层接口,调用端只需要跟这个接口发生调用。

image20220105172219716

注意事项

  • 系统需要分层设计可以使用外观模式。
  • 屏蔽了子系统的细节。解决多个复杂接口带来的调用困难,简化操作。
  • 合理使用外观模式,直接调用模块很方便时就不要使用外观模式。

MyBatis 中的 Configuration 创建 MetaObject 使用了外观模式。

image20220105171559783

10 享元模式

image20220106150153280

享元模式:运用共享技术有效地支持大力度的对象。

能解决重复创建对象的内存浪费问题。Eg,String常量池、数据库连接池。

image20220106152043073

Integer类中就使用到了享元模式, -128 ~ 127 共享缓存池中的对象,范围外的就不在缓存池了,而是创建新的对象。所以 Integer.valueOf(127) == Integer.valueOf(127) 为 true。

11 代理模式

好处:对目标对象的方法增强,即扩展目标对象的功能。

目标对象可以是:远程对象,创建开销大的对象,需要安全控制的对象。

三种代理形式:静态代理,JDK 动态代理,cglib 代理。

静态代理:

1.定义一个接口及其实现类;

2.创建一个代理类同样实现这个接口

3.将目标对象注入进代理类,然后在代理类的对应方法中调用目标类中的对应方法。

jdk动态代理:

被代理的目标对象必须实现接口。

1.定义一个接口及其实现类;

2.定义一个工厂类,实现 InvocationHandler 接口并重写invoke方法,在 invoke 方法中调用目标对象的方法(被代理类的方法)并自定义一些处理逻辑

3.通过 Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) 方法创建代理对象

cglib动态代理:

被代理的目标对象是普通类,不需要实现接口

1.定义一个被代理普通类;

2.定义一个工厂类,实现 MethodInterceptor 接口并重写 intercept 方法,intercept 用于拦截增强被代理类的方法,和 JDK 动态代理中的 invoke 方法类似;

3.通过 Enhancer 类的 create()创建代理类

12 模板方法模式

image20220411221605337

制作豆浆

image20220411221851566

注意事项和细节:
基本思想:算法只存在一个地方(父类中),易修改。

实现了最大代码复用。

模板方法都要加上final关键字,防止子类修改模板方法。

适用场景:当要完成某个过程,该过程要执行一系列步骤,这一系列步骤基本相同,个别步骤在实现时可能不同。

缺点:每一个不同的实现都需要一个子类实现,导致类的个数增加,使系统更加庞大。

13 命令模式

命令模式,将发起请求、执行请求的对象解耦。

缺点:可能导致某些系统有过多的具体命名类,增加系统的复杂度。

14 访问者模式

访问者模式

访问者模式解决测评系统:

符合单一职责原则,扩展性、灵活性更好。

缺点:违反了依赖倒转原则。访问者依赖的是具体的元素,而不是抽象元素。对访问者公布细节。

15 迭代器模式

优点

1.提供了一个统一的方法遍历对象,用户不用考虑聚合类型,使用一种方法就可以遍历对象;

2.符合单一职责原则,一个类只有一个引起变化的原因。

3.隐藏聚合的内部结构,客户端要遍历集合的时候只能取到迭代器,而不会知道聚合的具体构成。

缺点

每个聚合对象都要一个迭代器,会产生多个迭代器不好管理类。

16 观察者模式

需求:天气预报

观察者模式解决天气预报

17 中介者模式

中介者模式,用一个中介对象来封装一系列的对象交互。

中介者模式解决智能家庭管理

18 备忘录模式

19 解释器模式

四则运算问题

20 状态模式

APP抽奖活动

21 策略模式

鸭子问题——传统解决方案

带来的问题

鸭子问题——策略模式解决方案

策略模式,定义算法族,封装起来可以相互替换。

鸭子问题具体的策略:

22 责任链模式

需求

image20220408195145700

image20220408222810388

image20220408230955609

image20220408234622620

image20220408234631119

springMVC的拦截器使用到了责任链模式

image20220408235334723

image20220408235659441

注意事项和细节:

  • 请求和处理分开,实现解耦,提高系统的灵活性
  • 简化对象,使对象不需要知道链的结构
  • 链特别长的时候,性能会受到影响,因此需要控制链的节点数
  • 调试不方便,采用了类似递归的方式
  • 适用场景:多个对象处理同一个请求,比如:多级请求,请求/加薪等审批流程、Java web中Tomcat对Encoding的处理、拦截器。
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/little_lunatic/advance.git
git@gitee.com:little_lunatic/advance.git
little_lunatic
advance
advance
main

搜索帮助