代理模式

代理模式java中23种设计模式之一

一个类不能或不方便访问另一个类时,通过代理来间接进行访问,代理起到桥梁的作用

java开发原则:

开闭原则                (每一个模块只做一件事情,解耦)

单一职责原则         (一个类不能或不方便访问另一个类时,通过代理来间接进行访问,代理起到桥梁的作用)

静态代理

实现步骤:

 1. 分为代理者和被代理者(代理者与被代理者有相同的功能,也就是实现相同的接口)

 2. 代理者包含一个被代理者的对象(代理者对象传入被代理者对象中)

 3. 代理者调用方法时,要调用被代理者的方法,同时再加入新功能

共同接口

package com.cdz.static_agent_computer;

public interface IComputerSell {
    /**
     * 卖电脑
     */
    void sellComputer();
}

电脑生产商

package com.cdz.static_agent_computer;
/**
 * 电脑生产商(被代理者)
 */
public class MiComputerFactory  implements  IComputerSell{
    /**
     * 相同方法:销售电脑
     */
    @Override
    public void sellComputer() {
        System.out.println("卖小米电脑");
    }
}

 电脑销售商

package com.cdz.static_agent_computer;
/**
 *电脑代理商(代理者)
 */
public class MiComputerShop implements IComputerSell {
    private IComputerSell miComputerFactory;
    //代理者包含被代理者的对象,将被代理者对象传入到代理者对象中
    public MiComputerShop(IComputerSell miFactory){
        this.miComputerFactory=miFactory;
    }
    /**
     * 都有的方法:销售电脑
     * 并加入新功能
     */
    @Override
    public void sellComputer() {
        //扩展功能
        System.out.println("给电脑公司打广告");
        //调用被代理者方法
        miComputerFactory.sellComputer();
        System.out.println("给电脑做销售");
    }
}

测试:

package com.cdz.test;
import com.cdz.static_agent_computer.HuaWeiFactory;
import com.cdz.static_agent_computer.IComputerSell;
import com.cdz.static_agent_computer.MiComputerShop;
public class AgentTest {
    public static void main(String[] args) {
        //创建被代理者对象
        IComputerSell miFactory = new HuaWeiFactory();
        //创建代理者对象
        IComputerSell miShop =new MiComputerShop(miFactory);
        //调用代理方法
        miShop.sellComputer();
    }
}

 

:静态代理的代理者只能代理一种业务,如果有多个业务就需要多个代理者

动态代理

原理:通过动态代理创建类,传入实现不同接口的被代理对象,会通过反射读取被代理对象的属性和方法,创建新代理类

(生成字节码),再创建代理类的对象。

动态代理实现方法:

一、. JDK动态代理

实现步骤:

1. 实现InvocationHandler接口

2. 代理者包含一个被代理者的对象(代理者对象传入被代理者对象中)

3. 实现接口方法invoke方法,在方法中调用被代理者方法,并扩展功能

4. 使得Proxy. newProxyInstance创建代理对象

第二步同上不需要实现方法即可

第一步,第三、四步:

package com.cdz.jdkagent;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//应用技术反射
public class MyJDKAgentShop implements InvocationHandler {
    //定义一个被代理者的对象
    private Object factory;

    //实现接口方法invoke
    @Override
    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
       //功能扩展
        System.out.println("给产品打广告");
        //调用被代理者的方法(实现原理:反射)
        method.invoke(factory,objects);
        System.out.println("给产品做销售");
        return null;
    }

    //设置被代理者对象,使用Proxy.newProxyInstance并创建代理者对象
    public Object setFactory(Object factory) {
        this.factory = factory;
        //创建代理对象
        Object p = Proxy.newProxyInstance(factory.getClass().getClassLoader(),
                factory.getClass().getInterfaces(),
                this);
        return p;
    }
}

测试:

package com.cdz.test;

import com.cdz.static_agent_computer.IComputerSell;
import com.cdz.static_agent_computer.MiComputerFactory;
import com.cdz.jdkagent.MyJDKAgentShop;
import com.cdz.static_agent_tel.ITelSell;
import com.cdz.static_agent_tel.MiTelFactory;

public class JDKAgentTest {
    public static void main(String[] args) {
        //创建电脑的被代理对象
        IComputerSell sell1=new MiComputerFactory();
        //创建手机的被代理对象
        ITelSell sell2= new MiTelFactory();

        //创建动态代理对象
        MyJDKAgentShop shop=new MyJDKAgentShop();

        //创建电脑的动态代理对象
        IComputerSell proxy1 = (IComputerSell)shop.setFactory(sell1);
        //调用代理对象
        proxy1.sellComputer();

        //创建卖手机的动态代理对象
        ITelSell proxy2 = (ITelSell) shop.setFactory(sell2);
        //调用代理对象
        proxy2.sellTel();
    }
}

 invoke方法参数:

Object invoke(Object proxy, Method method, Object[] args)方法

proxy 代理者对象

method 需要调用方法

args 参数的数组

返回值是method调用后的结果

Proxy.newProxyInstance对象的参数:

Object p = Proxy.newProxyInstance(factory.getClass().getClassLoader(),factory.getClass().getInterfaces(),this);

ClassLoader classLoader,       类的加载器,被代理对象.getClass().getClassLoader()

Class[] interfaces,                   被代理对象实现接口的数组,被代理对象.getClass().getInterfaces()

InvocationHandler h                代理对象,this

 

二、 CGLIB动态代理

被代理的类不需要实现接口,CGLib是通过继承机制实现的,CGLib是动态生成了被代理类的子类,被代理的类必须能被继承。

实现步骤:

1. 引入依赖

 <!-- https://mvnrepository.com/artifact/cglib/cglib -->
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.3.0</version>
        </dependency>

2.  实现MethodInterceptor接口

3. 使用Enhancer创建代理对象

//2. 实现接口
public class MyCGLibShop implements MethodInterceptor {
    //被代理对象
    private Object factory = null;

    public Object createProxy(Object factory){
        this.factory = factory;
        //3. 帮助创建代理类的工具
        Enhancer enhancer = new Enhancer();
        //给代理类设置父类
        enhancer.setSuperclass(this.factory.getClass());
        //设置方法的回调(调用代理对象的方法时执行的代码)
        enhancer.setCallback(this);
        //创建并返回代理类的对象
        return enhancer.create();
    }

4. 创建代理者调用方法

 @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("CGLib给产品打广告");
        //调用父类(被代理者)的方法
        methodProxy.invokeSuper(o,objects);
        System.out.println("CGLib给产品做售后");
        return null;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值