设计模式-2 结构型模式

一、代理模式

1、举例

海外代购

2、代理基本结构图

设计模式-2 结构型模式_第1张图片

3、静态代理

1、真实类实现一个接口,代理类也实现这个接口。

2、代理类通过真实对象调用真实类的方法。

4、静态代理和动态代理的区别

1、静态代理在编译时就已经实现了,编译完成后代理类是一个实际的class文件。

2、动态代理是在运行时动态生成的,即编译完成后没有实际的class文件,而是在运行时动态生成类字节码,再加载到JVM中。

5、JDK动态代理实现

核心:构造代理对象,按JDK要求获取参数,让JDK生成代理对象。

// 生成代理对象 - 核心
Dinner proxy = (Dinner) Proxy.newProxyInstance(classLoader, interfaces, h);
package allwe.testProxy;

/**
 * 定义一个晚餐接口
 */
public interface Dinner {

    void eat(String foodName);

    void drink(String juiceName);
}
package allwe.testProxy;

import lombok.Data;

/**
 * 定义人 - 实现晚餐接口
 */
@Data
public class Person implements Dinner {

    private String name;

    public Person(String name) {
        this.name = name;
    }

    @Override
    public void eat(String foodName) {
        System.out.println(this.name + "吃" + foodName);
    }

    @Override
    public void drink(String juiceName) {
        System.out.println(this.name + "喝" + juiceName);
    }
}
package allwe.testProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * 我的调用处理器 - 设定增强规则
 */
public class MyInvocationHandler implements InvocationHandler {

    private final Dinner dinner;

    public MyInvocationHandler(Dinner dinner) {
        this.dinner = dinner;
    }

    /**
     * 定义增强规则
     *
     * Object proxy     代理对象
     * Method method    被代理的方法
     * Object[] args    被代理方法运行时的实参
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        if (method.getName().equals("eat")) {
            System.out.println("前置增强===================饭前洗手");
            // 运行eat方法
            method.invoke(dinner, args);
            System.out.println("后置增强===================饭后洗碗");
        } else if (method.getName().equals("drink")) {
            System.out.println("前置增强===================打开瓶盖");
            // 运行eat方法
            method.invoke(dinner, args);
            System.out.println("后置增强===================关上瓶盖");
        } else {
            return method.invoke(dinner, args);
        }
        return null;
    }
}
package allwe.testProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

/**
 * 动态代理实现
 */
public class TestProxy {

    // 通过Proxy动态代理获取一个代理对象,在代理对象中,对某个方法增强
    public static void main(String[] args) {

        // 创建一个人 - 张三
        Dinner dinner = new Person("张三");

        // 被代理对象的类加载器
        ClassLoader classLoader = dinner.getClass().getClassLoader();
        // 被代理对象所实现的所有接口
        Class[] interfaces = dinner.getClass().getInterfaces();
        // 执行处理器对象 - 专门用于定义增强的规则的
        InvocationHandler h = new MyInvocationHandler(dinner);

        // 生成代理对象 - 核心
        Dinner proxy = (Dinner) Proxy.newProxyInstance(classLoader, interfaces, h);

        // 使用代理对象调用Dinner接口的方法
        proxy.eat("馒头");
        proxy.drink("可乐");
    }
}

6、Cglib动态代理实现

核心:构造代理对象,按CGLIB要求获取参数,让CGLIB生成代理对象。

// 1.创建一个Enhancer对象
Enhancer enhancer = new Enhancer();
// 2.设置真实对象的类
enhancer.setSuperclass(personClass);
// 3.设置增强逻辑
enhancer.setCallback(methodInterceptor);
// 4.创建代理对象
Person personProxy = (Person) enhancer.create();
package allwe.testCGLib;

import lombok.Data;

/**
 * 定义人
 */
@Data
public class Person {

    private String name;

    // Cglib使用这个构造器创建真实对象
    public Person() {
        this.name = "张三";
    }

    public void eat(String foodName){
        System.out.println(this.name + "吃" + foodName);
    }
}
package allwe.testCGLib;

import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * 我的方法拦截器 - 定义方法拦截规则
 */
public class MyMethodInterceptor implements MethodInterceptor {

    /**
     * Object o                    生成之后的代理对象
     * Method method               父类中原本要执行的方法
     * Object[] objects            方法在被调用时接收的实参
     * MethodProxy methodProxy     子类中重写的  父类方法
     */
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("==========前置增强==========");

        // 执行子类对象方法   -->  son.super.method(args)
        Object res = methodProxy.invokeSuper(o, objects);

        System.out.println("==========后置增强==========");
        return res;
    }
}
package allwe.testCGLib;

import org.junit.jupiter.api.Test;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;

public class TestCglib {

    @Test
    public void testCglib() {
        // 获取被代理的类
        Class personClass = Person.class;
        // 定义增强规则
        MethodInterceptor methodInterceptor = new MyMethodInterceptor();

        // 获取一个Person的代理对象
        // 1.创建一个Enhancer对象
        Enhancer enhancer = new Enhancer();
        // 2.设置真实对象的类
        enhancer.setSuperclass(personClass);
        // 3.设置增强逻辑
        enhancer.setCallback(methodInterceptor);
        // 4.创建代理对象
        Person personProxy = (Person) enhancer.create();

        // 使用代理对象执行方法
        personProxy.eat("米饭");
    }
}

二、桥接模式

1、定义

在软件开发中,桥接模式将两个独立变化的维度进行了解耦,不是将两者耦合在一起,形成多继承的结构。

2、举例

毛笔和蜡笔,大中小号,12种颜色。

3、结构:实体与行为分离

设计模式-2 结构型模式_第2张图片

4、核心

首先要识别出一个类所具有的两个独特的变化维度,将它们设计为两个独立的继承等级结构,为两个维度都提供抽象层,并建立抽象

你可能感兴趣的:(设计模式,设计模式)