• 黑马-设计模式-笔记(未完)


    一、基础

    UML类图

    可见性:

    • + public
    • - private
    • #protected
      表示方式:
    • 属性:可见性 名称:类型[=默认值]
    • 方法:可见性 名称(参数)[:返回类型]
      关系:
    • 关联关系:实线,引用关系,类属性里有另一个类
    • 聚合关系:空心菱形,表示整体和部分,类属性是另一个类的集合
    • 组合关系:实心菱形,强烈聚合关系,类属性是另一个类,控制它的存在
    • 依赖关系:虚线,类方法参数里有另一个类,(耦合度最低)
    • 继承关系:空心实线三角,泛化关系,表示一般与特殊,(耦合度最高)
    • 实现关系:空心虚线三角,接口和实现类关系
    软件设计原则

    单一职责原则:一个类只负责一个职责
    里氏代换原则:子类可以直接替换父类,可以扩展父类的方法,但不能改变父类原有功能
    开闭原则:对扩展开放,对修改关闭,实现热插拔
    依赖倒转原则:模块间要依赖抽象,不要依赖实现,客户和实现解耦
    接口隔离原则:接口最小粒度设计,一个类对另一个类尽量少依赖不相关的方法,抽象接口细拆开进行实现
    迪米特法则:两个模块无需直接通讯就无需直接调用,使用第三方转发降低耦合度
    合成复用原则:尽量先使用关联关系实现,其次才是继承复用,父类对子类是透明的(白箱复用)

    一、创建型模式

    如何创建对象,将对象的创建和使用分离

    1.单例模式
    结构
    • 单例类:只能创建一个实例的类
    • 访问类:使用单例类
    分类
    • 饿汉式:类加载就会导致该单例对象被创建
      静态变量方式
    public class Singleton {  
      
        // 1.私有构造方法  
        private Singleton() {}  
      
        // 2.在本类中创建该类对象  
        private static Singleton instance = new Singleton();  
      
        // 3.提供公共访问方式  
        public static Singleton getInstance() {  
            return instance;  
        }  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    静态代码块方式

    public class Singleton {  
      
        // 1.私有构造方法  
        private Singleton() {}  
      
        // 2.声明Singleton类型变量  
        private static Singleton instance; // null  
      
        // 3.静态代码块赋值  
        static {  
            instance = new Singleton();  
        }  
      
        // 4.提供公共访问方式  
        public static Singleton getInstance() {  
            return instance;  
        }  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    枚举方式
    枚举类线程安全只会装载一次,唯一不会被破坏的单例模式

    public enum Singleton {  
        INSTANCE;  
    }
    
    • 1
    • 2
    • 3
    • 懒汉式:首次使用对象时才被创建
      方式一:判断并加锁
    public class Singleton {  
      
        // 1.私有构造方法  
        private Singleton() {}  
      
        // 2.声明Singleton类型变量  
        private static Singleton instance;  
      
        // 3.提供公共访问方式  
        public static synchronized Singleton getInstance() {  
            // 判断instance是否为null  
            if (instance == null) {  
                instance = new Singleton();  
            }  
            return instance;  
        }  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    方式二:双重检查锁 写操作才加锁优化性能

    public class Singleton {  
      
        // 私有构造方法  
        private Singleton() {}  
      
        // 声明对象 需要volatile保证有序性
        private static volatile Singleton instance;
      
        // 对外提供方法  
        public static Singleton getInstance() {  
            // 第一次判断  
            if (instance == null) {  
                synchronized (Singleton.class){  
                    // 第二次判断  
                    if (instance == null) {  
                        instance = new Singleton();  
                    }  
                }  
            }  
      
            return instance;  
        }  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    方式三:静态内部类
    JVM加载时不会加载内部类,只有调用内部类时才会加载

    public class Singleton {  
      
        // 私有构造方法  
        private Singleton() {}  
      
        // 定义一个静态内部类  
        // JVM加载时不会加载内部类,只有调用内部类时才会加载  
        private static class SingletonHolder{  
            // 在内部类中声明并初始化外部类的对象  
            private static final Singleton INSTANCE = new Singleton();  
        }  
      
        // 对外提供方法  
        public static Singleton getInstance() {  
            return SingletonHolder.INSTANCE;  
        }  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    问题
    • 破坏单例模式
      • 序列化、反序列化:通过ObjectOutStream和ObjectInputStream对对象进行反序列化生产新的对象
        • 解决方法:在单例类中增加readResolve()方法返回单例对象
      • 反射:通过反射获取无参构造函数并放权
        • 解决方法:在单例类无参构造方法中增加判断并返回单例对象
    2.工厂模式
    简单工厂模式/静态工厂模式

    把对象创建和业务分开,有新产品只需要修改工厂类;但是产品和工厂还有耦合,新产品还需要改工厂违反开闭

    组成
    • 具体工厂:提供了创建产品的规范,调用者通过该方法创建产品
    • 抽象产品:定义产品规范
    • 具体产品:实现或继承抽象产品的子类
      ![[20240424_设计模式 GoF_1.png]]
    工厂方法模式

    用户只需知道具体工厂名称;新增产品只需添加具体产品和具体工厂类,无需对原工厂修改;但是增加了系统复杂

    组成
    • 抽象工厂:提供创建产品的接口,调用者通过它访问具体工厂来创建产品
    • 具体工厂:提供了创建产品的规范,调用者通过该方法创建产品
    • 抽象产品:定义产品规范
    • 具体产品:实现或继承抽象产品的子类
      在这里插入图片描述
    抽象工厂模式

    可以保证用户使用同一个产品族的产品;但是产品族加一个产品,所有工厂类都需要修改

    组成
    • 抽象工厂:提供创建产品的接口,包含多个创建产品的方法,创建多个不同等级的产品
    • 具体工厂:提供了创建产品的规范,调用者通过该方法创建产品
    • 抽象产品:定义产品规范
    • 具体产品:实现或继承抽象产品的子类
      ![[20240424_设计模式 GoF_2.png]]
    3.原型模式

    用一个已创建的实例为原型创建新对象,适用于对象创建复杂,对性能安全有要求

    浅克隆:非基本类型指向原有内存地址
    深克隆:完全一致并独立的拷贝,可以使用序列化或者递归浅克隆或其他方式实现

    组成
    • 抽象原型类:规定了具体原型对象必须实现的clone方法,通常是Cloneable接口
    • 具体原型类:实现抽象原型类的clone方法
    • 访问类:使用具体原型类的clone方法来复制新对象
    4.建造者模式

    将复杂对象的构建和表示分离,使同样的构建可以创建不同的表示
    适用于构建复杂且各个部分独立,构建流程相对一致的
    可以通过内部建造类实现链式编程

    组成
    • 抽象建造者类:接口规定都有哪些部分要创建
    • 具体建造者类:实现抽象建造者,提供具体构建各个部分的方法,完成后提供产品实例
    • 产品类:要创建的复杂对象
    • 指挥者类:调用具体建造者创建各个部分,只负责按顺序或完整创建
      在这里插入图片描述

    二、结构型模式

    如何将类或对象按布局组成更大的结构

    1.代理模式

    访问对象不直接引用目标对象;有静态代理(编译时生成)和动态代理(java运行时动态生成 JDK代理、CGLib代理)

    组成
    • 抽象主题类:通过接口或抽象类声明真实主题和代理对象的业务方法
    • 真实主题类:实现具体业务,是代理对象代表的真实对象,是最终要引用的对象
    • 代理类:提供了与真实主题相同的接口,内部是对真实主题引用
    静态代理

    直接在代理类中增加真实主题类的成员变量,在方法中调用真实主题类的成员变量
    在这里插入图片描述

    JDK动态代理

    java中提供动态代理类Proxy,里面有静态方法newProxyInstance获取代理对象

    2.适配器模式
    3.桥接模式
    4.装饰者模式
    5.外观模式
    6.享元模式
    7.组合模式

    三、行为型模式

    如何让类或对象协作完成任务

    1.模板方法模式
    2.策略模式
    3.命令模式
    4.职责链模式
    5.状态模式
    6.观察者模式
    7.中介者模式
    8.迭代器模式
    9.访问者模式
    10.备忘录模式
    11.解释器模式
  • 相关阅读:
    基于el-form实现自动展开/收起的查询条件组件
    基于工业互联网平台智能制造方案【工业互联网甄选联盟】
    【LeetCode-中等题】39. 组合总和
    【开源库推荐】go-linq 强大的语言集成查询库如,ORM一般丝滑处理内存数据
    【面试刷题】——C++的特点简单说明
    【附源码】计算机毕业设计SSM实验室设备明细管理系统
    mac pro M1(ARM)安装:.Net、C#开发环境
    突发 Chatgpt之父被开,GPT放开注册,注册难度大幅降低!
    点云目标检测——pointpillars环境配置与训练
    Go 语言代码断行规则详解
  • 原文地址:https://blog.csdn.net/qq_41207861/article/details/138193857