2025-05-29-Thu-T-设计模式

1. 设计模式相关内容介绍

1.1 设计模式概述

设计模式分类:

  • 创建者模式: 将对象的创建与使用分离(解耦)

    • 单例
    • 原型
    • 工厂方法
    • 抽象工厂
    • 建造者
  • 结构型模式: 如何将类或对象按照某种布局组成更大的结构

    • 代理
    • 适配器
    • 桥接
    • 装饰
    • 外观
    • 享元
    • 组合
  • 行为型模式: 描述类或对象之间如何相互协作,以及如何分配职责

    • 模板方法
    • 策略
    • 命令
    • 职责链
    • 状态
    • 观察者
    • 中介者
    • 迭代器
    • 访问者
    • 备忘录
    • 解释器

1.2 UML类图

UML是统一建模语言

  • 用例图
  • 类图
  • 对象图
  • 状态图
  • 活动图
  • 时序图
  • 协作图
  • 构件图

类的表示方式

  • 类名
  • 属性和方法

+表示public

- 表示private

# 表示protected

属性的完整表示方式:可见性 名称:类型 [=初始值]

方法的完整表示方式:可见性 名称(参数列表) [:返回类型]

类之间的关系表示方法

  • 单项关联

  • 双向关联

  • 自关联: Employee.leader

  • 聚合关系

  • 组合关系

  • 依赖关系

  • 继承关系

  • 实现关系

1.3 软件设计原则

1.1 开闭原则

对扩展开放,对修改关闭

实现方式: 接口和抽象类 impliments

1.2 里氏代换原则

任何基类(父类)可以出现的地方,子类一定可以出现。

1.3 依赖倒转/依赖倒置原则

改进后:

1.4 接口隔离原则

1.5 迪米特法则

1.6 合成复用原则

单一职责原则

  • 基本介绍

对类来说的,一个类应该只负责一个职责。

2. 创建者模式(5种)

  • 关注点: 如何创建对象
  • 主要特点: 将对象的创建和使用分离

降低系统耦合度, 使用者不需要关系创建细节.

2.1 单例模式

  • 单一的类
  • 只创建一个对象(只调用一次私有化构造方法) 赋值给静态变量
  • 公共的静态访问方式

饿汉式

  • 静态变量
public class SingletonStaticHunger {
    private static SingletonStaticHunger instance = new SingletonStaticHunger();
    private SingletonStaticHunger() {} 

    public static SingletonStaticHunger getInstance() {
        return instance;
    }
}
  • 枚举方式
enum EnumSigleton{
    INSTANCE;
}

懒汉式

  • 线程不安全
public class LazySingletonUnsafe {
    private static LazySingletonUnsafe instance;
    private LazySingletonUnsafe() {
    }
    public static LazySingletonUnsafe getInstance() {
        if(instance ==null){
            instance = new LazySingletonUnsafe();
        }
        return instance;
    }
}
  • 线程安全
public class LazySingletonSafe {
    private static LazySingletonSafe instance;
    private LazySingletonSafe() {}
    public static synchronized LazySingletonSafe getInstance() {
        if (instance == null) {
            instance = new LazySingletonSafe();
        }
        return instance;
    }
}
  • 双重检查锁
public class LazySingletonSafeDoubleCheck {
    private static  LazySingletonSafeDoubleCheck instance; // 静态变量 
    private LazySingletonSafeDoubleCheck() {}              //私有化构造器 
    public static LazySingletonSafeDoubleCheck getInstance() { // 静态变量
        if(instance == null) { // 第一次检查放行instance为空的请求
            synchronized (LazySingletonSafeDoubleCheck.class) {
                if(instance == null) { // 第二次放行instance为空的请求
                    instance = new LazySingletonSafeDoubleCheck();
                }
            }
        }
        return instance;
    }
}
 

优先使用双重检查锁

//volatile
public class LazySingletonSafeDoubleCheck {
    /**
    * 正常程序: 先把空间分配给变量,再赋值到空间
    * 编译后指令重排:先把赋值到空间,再把空间分配给变量
    */
    private static volatile LazySingletonSafeDoubleCheck instance; // volatile保证指令有序,防止多线程环境下空指针异常
    private LazySingletonSafeDoubleCheck() {}
    public static LazySingletonSafeDoubleCheck getInstance() {
        if(instance == null) {
            synchronized (LazySingletonSafeDoubleCheck.class) {
                if(instance == null) {
                    instance = new LazySingletonSafeDoubleCheck();
                }
            }
        }
        return instance;
    }
}
  • 静态内部类方式 (类加载过程是线程an'q
public class LazyInnerClass {

    private LazyInnerClass() {} // 私有化构造器
    private static class LazyInnerClassHolder { // 私有化静态内部类,被访问时才会被加载到堆内存
        public static final LazyInnerClass INSTANCE = new LazyInnerClass(); // final 防止外部类二次修改
    }
    public static LazyInnerClass getInstance2() { // 静态方法
        return LazyInnerClassHolder.INSTANCE;
    }
}

2.2 工厂模式

简单工厂模式 - 产品创建纵向解耦

简单工厂模式不是一种设计模式,反而是一种编程习惯

简单工厂模式包含如下角色:

  • 具体工厂: 提供创建产品的方法,调用者通过方法来获取产品
  • 抽象产品: 定义规范,描述产品的主要特性和功能
  • 具体产品: 实现或继承抽象产品的子类

缺点:对修改没有关闭,新增产品需要修改工厂类

package com.pattern.factory;

public class SimpleFactory {
    /**
     * 用户端 - 使用产品
     * 根据产品类型获取产品
     * 用户不需要写创建产品的判断逻辑
     * @param args
     */
    public static void main(String[] args) {
        ProductInterface product = FactorySimple.createProduct(ProductB.class);
        if(product != null) {
            product.function();
        }
    }
}

/**
 * 产品工厂
 * 负责生产具体产品
 * 书写判断逻辑
 */
class FactorySimple {

    // 利用多态来返回产品
    public static ProductInterface createProduct(Class<? extends ProductInterface> clazz) {
        if(ProductB.class.isAssignableFrom(clazz)) {
            return new ProductB();
        }else if(ProductA.class.isAssignableFrom(clazz)) {
            return new ProductA();
        }
        return null;
    }

}

/**
 * 抽象产品
 * 抽象产品的特征和功能
 */
interface ProductInterface{
    void function();
}


/**
 * 具体产品
 * 实现产品具体功能
 */
class ProductA implements ProductInterface{

    @Override
    public void function() {
        System.out.println("A 功能");
    }

}

/**
 * 具体产品
 * 实现产品具体功能
 */
class ProductB implements ProductInterface{
    @Override
    public void function() {
        System.out.println("B功能");
    }
}

对扩展开放,但是对修改没有关闭掉。新增产品类型需要修改工厂类。工厂和产品间还存在较大耦合

完全遵循开闭原则

定义一个用于创建对象的接口,让子类决定实例化哪个产品对象。工厂方法使用一个产品类的实例化延迟到工厂的子类

工厂抽象方法主要角色:

  • 抽象工厂: 提供创建产品的接口,调用者通过它访问具体的工厂方法来创建产品
  • 具体工厂: 完成具体产品的创建。
  • 抽象产品: 定义产品规范,描述产品的主要特性和功能
  • 具体产品: 实现抽象产品的接口。

缺点:每增加一个具体产品类,需要增加一个具体工厂类,增加了系统复杂度

package com.pattern.factory;

public class FunctionFactory {
    public static void main(String[] args) {
        Factory1 factory1 = new Factory1();
        Factory2 factory2 = new Factory2();
        Product product = factory1.create(Product1.class);
        Product product1 = factory2.create(Product2.class);

        System.out.println(product);
        System.out.println(product1);

    }

}

/**
 * 修改关闭
 */
interface Factory{
    Product create(Class<? extends Product> clazz);
}

/**
 * 扩展开放
 */
class Factory1 implements Factory{


    @Override
    public Product create(Class<? extends Product> clazz) {
        return Product1.class.isAssignableFrom(clazz) ? new Product1() : null;
    }
}

/**
 * 扩展开放
 */
class Factory2 implements Factory{

    @Override
    public Product create(Class<? extends Product> clazz) {
        return Product2.class.isAssignableFrom(clazz) ? new Product2() : null;
    }
}


/**
 * 修改关闭
 */
interface Product{
    void function();
}

/**
 * 扩展开放
 */
class Product1 implements Product{
    @Override
    public void function() {

    }
}

/**
 * 扩展开放
 */
class Product2 implements Product{
    @Override
    public void function() {

    }
}



抽象工厂模式 - 工厂创建横向内聚

抽象工厂模式是一种为访问类提供一个创建一组相关或相互依赖对象的接口。访问类无需指定所要产品的具体类,就能得到同族的不同等级的产品。

抽象工厂是对工厂方法的升级,工厂方法只生产同一等级的

主要角色:

  • 抽象工厂:提供了创建产品的接口,包含多个创建产品的方法,可以创建多个不同等级的产品
  • 具体工厂:实现抽象工厂,完成具体产品的创建
  • 抽象产品:描述产品特性,定义规范
  • 具体产品:实现抽象产品

缺点:当产品族当中新增一个产品类型时,所有工厂类都需要进行修改

package com.pattern.factory;

public class AbstractFactory {
    public static void main(String[] args) {
        Factory_1 factory1 = new Factory_1();
        Factory_2 factory2 = new Factory_2();
        TypeAProduct a = factory1.createA();
        TypeBProduct b = factory1.createB(); // 因为_Factory内聚了两个创建方法,所以不需要再实现一个工厂创建TypeBProduct
        TypeAProduct a1 = factory2.createA();
        TypeBProduct b1 = factory2.createB();
    }
}


/**
 * 修改关闭
 * 按照不同分类进行产品创建
 * 前提是确定了该分类不会再增减。、
 */
interface _Factory {
    TypeAProduct createA();
    TypeBProduct createB();
}

class Factory_1 implements _Factory {

    @Override
    public TypeAProduct createA() {
        return new ProductA1();
    }

    @Override
    public TypeBProduct createB() {
        return new ProductB1();
    }
}
class Factory_2 implements _Factory {

    @Override
    public TypeAProduct createA() {
        return new ProductA2();
    }

    @Override
    public TypeBProduct createB() {
        return new ProductB2();
    }
}



interface TypeAProduct {
    void functionA();
}

class ProductA1 implements TypeAProduct {

    @Override
    public void functionA() {
        System.out.println("ProductA1" + "functionA");
    }
}
class ProductA2 implements TypeAProduct {
    @Override
    public void functionA() {
        System.out.println("ProductA2" + "functionA");
    }
}



interface TypeBProduct {
    void functionB();
}
class ProductB1 implements TypeBProduct {

    @Override
    public void functionB() {
        System.out.println("ProductB1" + "functionB");
    }
}

class ProductB2 implements TypeBProduct {
    @Override
    public void functionB() {
        System.out.println("ProductB2" + "functionB");
    }
}

工厂模式扩展 - 使用配置文件让具体工厂和具体产品解耦

在工厂类中加载配置文件中的全类名,并通过反射创建产品对象进行存储。

spring中采用的就是这种方式

2.3 原型模式

用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型对象的新对象。

角色:

  • 抽象原型类: 规定了具体原型对象必须实现的clone()方法
  • 具体原型类:实现抽象原型类中的clone()方法,具体原型类是可以被复制的对象。
  • 访问类:使用具体原型类的clone()来复制对象

Java中的Object提供了clone方法来实现浅克隆。Cloneable 接口

使用场景:如果创建对象的过程非常复杂,就使用原型对象的方式进行创建对象, 性能和安全性的要求比较高

2.4 建造者模式


3. 结构型模式(7种)

结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构模式和对象结构模式,前者采用继承或实现机制来组织接口和类。后者采用组合或聚合来组合对象。

由于组合关系或聚合关系比继承或实现关系耦合度更低,满足‘合成复用原则’,所以对象结构模式比类结构模式具有更大的灵活性。

3.1 代理模式

分类:

  • 静态代理:编译时期生成代理类
  • 动态代理:java运行时动态生成代理类
    • JDK代理
    • CGLib代理

角色:

  • 抽象主题类Subject: 通过接口或抽象类声明真实主题和代理对象实现的业务方法
  • 真实主题类Real Subject: 实现了抽象主题中的具体业务,是代理对象所代表的真实对象,是最终要引用的对象。
  • 代理类Proxy: 提供了与真实主题相同的接口,其内部含有对真实主题的引用,它可以访问、控制或者扩展真实主题的功能。

静态代理

package com.pattern.proxy;

public class StaticProxy {
    public static void main(String[] args) {
        Proxy proxy = new Proxy();
        proxy.keyMethod();

    }
}

// 主题类:声明某个方法
interface Subject{
    void keyMethod();
}

//真实主题类:重写方法,实现具体操作
class RealSubject implements Subject{

    @Override
    public void keyMethod() {
        System.out.println("核心操作");
    }
}

//代理类:重写方法,调用真实主题类的方法,并添加额外功能
class Proxy implements Subject{
    private final RealSubject realSubject new RealSubject();
    @Override
    public void keyMethod() {
        System.out.println("代理操作1");
        realSubject.keyMethod();
        System.out.println("代理操作2");
    }
}

JDK动态代理

java运行时动态生成代理类

Java中提供了一个动态代理类Proxy,Proxy并不是我们所说的代理对象的类,而是提供了一个创建代理对象的静态方法newProxyInstance()方法来获取代理对象。


interface SubjectInterface{
    void keyMethod();
}
class Subject implements SubjectInterface{
	void keyMethod(){
        System.out.println("Key Method");
    }
}

class ProxyFactory{
    private static Subject sbj = new Subject();
    public SubjectInterface getProxy(){
        return Proxy.newProxyInstance(sbj.getClass.getClassLoader,obj.getClass.getInterfaces,
                                     new InvocationHandler(){
                                         public Object invoke(Object proxy, Method method, Object[] args){
                                             if("keyMethod".equals(method.getName())){ // 只对keyMethod方法增强
                                                 System.out.println("代理对象操作"); 
                                            	 method.invoke(sbj,args);
                                             }
                                             return proxy;
                                             
                                         }
                                     })
    } 
}

CGLab动态代理

JDK代理必须定义接口,对于没有接口定义的类,使用CGLib动态代理

引入cglib依赖

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>2.2.2</version>
</dependency>

JDK9之后添加JVM参数

--add-opens java.base/java.lang=ALL-UNNAMED
package com.pattern.proxy;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class CGLibProxy {
    public static void main(String[] args) {
        // 创建代理工厂对象
        CGLibProxyFactory cgLibProxyFactory = new CGLibProxyFactory();
        // 获取代理对象
        NormalClass proxyObject = cgLibProxyFactory.getProxyObject();
        proxyObject.sayHello();
        proxyObject.sayHello1();

    }
}


class NormalClass{

    public void sayHello(){
        System.out.println("普通方法");
    }

    public void sayHello1(){
        System.out.println("方法二");
    }

}


/**
 * 代理工厂
 * 用于获取代理对象
 */
class CGLibProxyFactory implements MethodInterceptor {
    private final NormalClass normal = new NormalClass();
    // 目标对象的子类
    public NormalClass getProxyObject(){
        //1. 创建Enhancer对象,类似于JDK代理中的Proxy类
        Enhancer enhancer = new Enhancer();
        //2. 设置父类的字节码对象
        enhancer.setSuperclass(NormalClass.class);
        //3. 设置回调函数, // 是下面的intercepted方法(MethodInterceptor)
        enhancer.setCallback(this);


        //4. 创建代理对象
        return  (NormalClass) enhancer.create();

    }
    
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("方法增强");
        Object invoke = method.invoke(normal, objects);
        return invoke;
    }
}

3.2 **适配器模式 ** - 能看懂

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

适配器Adapter包含的角色:

  • 目标接口Target:当前系统业务所期待的接口,它可以是抽象类或接口
  • 适配者类Adaptee:他是被访问和适配的现存组件库中的组件接口。真正运行任务对外提供的接口
  • 适配器类Adapter:接口转换器

类适配器模式

通过继承方式,耦合度高. 必须要有适配对象的目标接口才行,如果目标方法不在接口里将无法实现(因为不能继承两个类)

package com.pattern.adapter;

public class ClassAdapter {
    public static void main(String[] args) {

        runTarget(new Adapter());

    }

    public static void runTarget(TargetInterface target) {
        target.methodTarget();

    }

}

//现在要运行某功能支持的接口
interface TargetInterface{
    void methodTarget();
}

// 提供的功能
class Adtaptee{
    void method(){
        System.out.println("Adtaptee");
    }
}

//适配器(接口转换器)
class Adapter extends Adtaptee implements TargetInterface{

    @Override
    public void methodTarget() {
        method();
    }
}

对象适配器模式

通过聚合或组合的方式,耦合度低

采用将现有组件库中已经实现的组件引入适配器类中,该类同时重写当前系统的业务方法。

package com.pattern.adapter.object_adapter;

public class ObjectAdapter {

    public static void main(String[] args) {
        runTarget(new TargetClass());
        Adaptee adaptee = new Adaptee();
        Adapter adapter = new Adapter();
        adapter.setAdaptee(adaptee);
        runTarget(adapter);


    }

    public static void runTarget(TargetClass target){
        target.targetMethod();
    }

}

// 现在所支持的类和方法
class TargetClass{
    void targetMethod() {
        System.out.println("新方法");
    }
}

// 需要新加入的类和方法
class Adaptee{
    void oldMethod(){
        System.out.println("老方法");
    }
}


// 适配器 (转换器)
class Adapter extends TargetClass{

    private Adaptee adaptee;
    public void setAdaptee(Adaptee adaptee){
        this.adaptee = adaptee;
    }
    @Override
    public void targetMethod() {
        adaptee.oldMethod();
    }
}

3.3 装饰者模式

3.4 桥接模式

3.5 外观模式

3.6 组合模式

3.7 享元模式

4. 行为型模式(11种)

行为型模式用于描述程序在运行时复杂的流程控制。

4.1 **模板方法模式 **- 能看懂

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

主要角色:

  • 抽象类(Abstract class): 算法骨架
    • 模板方法:一个,定义算法结构. 一般使用final修饰
    • 基本方法:实现各个步骤的方法
      • 抽象方法:子类实现
      • 具体方法:父类实现,通用方法
      • 钩子方法:用于执行条件判断
  • 具体子类:实现功能的具体类
package com.pattern.template;

public class Template {
    public static void main(String[] args) {
        Reality reality = new Reality();
        reality.arch();

    }
}

//抽象类, 定义模板方法和基本方法
abstract class TemplateClass{
    private boolean flag = false;

    //模板方法(定义算法步骤)
    public final void arch(){
        init();
        if(isInited()){
            specialMethod();
        }
    }

    // 通用方法
    public void init(){
        System.out.println("init方法(基本方法)");
        flag = true;
    }

    // 钩子方法
    public boolean isInited(){
        return flag;
    }

    // 特殊方法,子类实现
    abstract void specialMethod();

}

//具体类,通过继承模板实现,代码量减少
class Reality extends TemplateClass{

    @Override
    void specialMethod() {
        System.out.println("特殊方法(子类实现)");
    }
}

4.2 策略模式

4.3 命令模式

4.4 职责链模式

4.5 状态模式

4.6 观察者模式 - 能看懂

又被称为‘发布-订阅’模式,定义了一对多的依赖关系。让多个观察者同时监听一个主题对象。主题对象在状态发生变化时,会通知所有的观察者对象,让他们自动更新。

角色:

  • 抽象主题(抽象被观察者): 把所有观察者维护到一个集合中,
  • 具体主题(具体的被观察者):
  • 抽象观察者(抽象的观察者)
  • 具体观察者(具体的观察者)
package com.pattern.observer;

import java.util.ArrayList;
import java.util.List;

public class Observer {
    public static void main(String[] args) {
        ConcretePublisher concretePublisher = new ConcretePublisher();
        concretePublisher.addObserver(new ConcreteObserver("张三"));
        concretePublisher.addObserver(new ConcreteObserver("李四"));
        concretePublisher.addObserver(new ConcreteObserver("王五"));
        concretePublisher.messageNotify("特大新闻》》》");
    }
}

// 订阅号
class ConcretePublisher{
    private List<AbstractObserver> observers = new ArrayList<AbstractObserver>();

    public void messageNotify(String news){
        for(AbstractObserver observer : observers){
            observer.message(news);
        }
    }

    public void addObserver(AbstractObserver observer){
        observers.add(observer);
    }

    public List<AbstractObserver> getObservers(){
        return observers;
    }
}

// 抽象观察者
abstract class AbstractObserver{

    public abstract void message(String news);
}

// 具体观察者
class ConcreteObserver extends AbstractObserver{
    private String name;

    ConcreteObserver(String name){
        this.name = name;
    }

    @Override
    public void message(String news) {
        System.out.println(this.name + "收到" +news);
    }
}

4.7 中介模式

4.8 迭代器模式

4.9 访问者模式

4.10 备忘录模式

4.11 解释器模式

5. 综合练习

posted @ 2025-11-23 21:38  飞↑  阅读(2)  评论(0)    收藏  举报