• Java之23种设计模式


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

    23种设计模式源码地址

    一、七大原则

    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 代理。

    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的处理、拦截器。
  • 相关阅读:
    PID 不能控制哪些系统?
    矩阵正定、负定、半正定、半负定
    KKT条件(不等式约束优化)
    腾讯OCR身份证正面识别
    小程序
    tomcat相关
    linux安装tomcat
    linux防火墙
    nginx操作
    Clean Code
  • 原文地址:https://www.cnblogs.com/qqkkOvO/p/16352869.html
Copyright © 2020-2023  润新知