设计模式学习(四)代理模式

目录

1.静态代理

2.动态代理

2.1JDK动态代理

2.2CGlib动态代理

3.静态代理和动态代理的区别:

4.代理模式的优缺点


    代理模式:为其他对象提供一种代理以控制这个对象的访问。

    目的:1.保护目标对象;2.增强目标对象

1.静态代理

UML类结构图:

代码实现:

(以父亲给儿子介绍对象为例)

Person接口

public interface Person {
    void findLove();
}

Son类

public class Son implements Person {
    public void findLove() {
        System.out.println("儿子要求:肤白貌美大长腿");
    }
}

Father类

public class Father implements Person {
    private Person person;

    public Father(Person person) {
        this.person = person;
    }

    public void findLove() {
        System.out.println("父亲物色对象");
        person.findLove();
        System.out.println("双方父母同意,确认关系");
    }
}

测试代码:

public class FatherProxyTest {
    public static void main(String[] args) {
        Father father = new Father(new Son());
        father.findLove();
    }
}

输出结果:

父亲物色对象
儿子要求:肤白貌美大长腿
双方父母同意,确认关系

2.动态代理

(此处以媒婆给闺女相亲为例)

2.1JDK动态代理

UML类结构图:

代码实现:

Person接口

public interface Person {
    void findLove();
}

Girl类

public class Girl implements Person {
    public void findLove() {
        System.out.println("高富帅");
        System.out.println("身高180cm");
        System.out.println("有6块腹肌");
    }
}
JDKMeipo类
public class JDKMeipo implements InvocationHandler {

    private Object target;

    public Object getInstance(Object obj) throws Exception {
        this.target = obj;
        Class<?> clazz = target.getClass();
        return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        Object obj = method.invoke(this.target, args);
        after();
        return obj;
    }

    private void before() {
        System.out.println("我是媒婆,我要给你找对象,现在已经确认你的需求");
        System.out.println("开始物色");
    }

    private void after() {
        System.out.println("OK的话,准备办事");
    }
}

测试代码:

public class JDKProxyTest {

    public static void main(String[] args) {
        try {
            Object obj = new JDKMeipo().getInstance(new Girl());
            Method method = obj.getClass().getMethod("findLove", null);
            method.invoke(obj);

            // JDK动态代理是动态生成一个$Proxy0动态类,
            // 可以通过以下代码将$Proxy0动态类输出到指定路径下,反编译查看
//            byte[] bytes = ProxyGenerator.generateProxyClass("$Proxy0", new Class[]{Person.class});
//            FileOutputStream os = new FileOutputStream("E://$Proxy0.class");
//            os.write(bytes);
//            os.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

输出结果:

我是媒婆,我要给你找对象,现在已经确认你的需求
开始物色
高富帅
身高180cm
有6块腹肌
OK的话,准备办事

反编译动态生成出来的$Proxy0.class文件,代码如下:

// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3) 

import com.gupaoedu.vip.pattern.proxy.Person;
import java.lang.reflect.*;

public final class $Proxy0 extends Proxy
    implements Person
{

    public $Proxy0(InvocationHandler invocationhandler)
    {
        super(invocationhandler);
    }

    public final boolean equals(Object obj)
    {
        try
        {
            return ((Boolean)super.h.invoke(this, m1, new Object[] {
                obj
            })).booleanValue();
        }
        catch(Error _ex) { }
        catch(Throwable throwable)
        {
            throw new UndeclaredThrowableException(throwable);
        }
    }

    public final void findLove()
    {
        try
        {
            super.h.invoke(this, m3, null);
            return;
        }
        catch(Error _ex) { }
        catch(Throwable throwable)
        {
            throw new UndeclaredThrowableException(throwable);
        }
    }

    public final String toString()
    {
        try
        {
            return (String)super.h.invoke(this, m2, null);
        }
        catch(Error _ex) { }
        catch(Throwable throwable)
        {
            throw new UndeclaredThrowableException(throwable);
        }
    }

    public final int hashCode()
    {
        try
        {
            return ((Integer)super.h.invoke(this, m0, null)).intValue();
        }
        catch(Error _ex) { }
        catch(Throwable throwable)
        {
            throw new UndeclaredThrowableException(throwable);
        }
    }

    private static Method m1;
    private static Method m3;
    private static Method m2;
    private static Method m0;

    static 
    {
        try
        {
            m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] {
                Class.forName("java.lang.Object")
            });
            m3 = Class.forName("com.gupaoedu.vip.pattern.proxy.Person").getMethod("findLove", new Class[0]);
            m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
            m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
        }
        catch(NoSuchMethodException nosuchmethodexception)
        {
            throw new NoSuchMethodError(nosuchmethodexception.getMessage());
        }
        catch(ClassNotFoundException classnotfoundexception)
        {
            throw new NoClassDefFoundError(classnotfoundexception.getMessage());
        }
    }
}

2.2CGlib动态代理

UML类结构图:

代码实现:

Customer类

public class Customer {
    public void findLove() {
        System.out.println("儿子要求:肤白貌美大长腿");
    }
}

CGlibMeipo类

public class CGlibMeipo implements MethodInterceptor {

    public Object getInstance(Class<?> clazz) throws Exception {
        // 相当于Proxy,代理的工具类
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        before();
        Object obj = methodProxy.invokeSuper(o, objects);
        after();
        return obj;
    }

    private void before() {
        System.out.println("我是媒婆,我要给你找对象,现在已经确认你的需求");
        System.out.println("开始物色");
    }

    private void after() {
        System.out.println("OK的话,准备办事");
    }
}

测试代码:

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

            // JDK是采用读取接口的信息
            // CGlib是采用覆盖父类方法
            // 目的:都是生成一个新的类,去实现增强代码逻辑的功能

            // JDK Proxy 对于用户而言,必须要有一个接口实现,目标类相对来说复杂
            // CGlib 可以代理任意一个普通的类,没有任何要求

            // CGlib 生成代理逻辑更复杂,效率低,
            // 但是调用效率更高,因为生成了一个包含了所有逻辑的FastClass,不再需要发射调用
            // JDK Proxy生成代理的逻辑简单,执行效率相对要低,每次都要反射动态调用

            // CGlib 有个坑,CGlib不能代理final的方法

            System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "E://cglib_proxy_classes");

            Customer obj = (Customer) new CGlibMeipo().getInstance(Customer.class);
            System.out.println(obj);
            obj.findLove();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

输出结果:

我是媒婆,我要给你找对象,现在已经确认你的需求
开始物色
我是媒婆,我要给你找对象,现在已经确认你的需求
开始物色
OK的话,准备办事
OK的话,准备办事
com.gupaoedu.vip.pattern.proxy.dynamicproxy.cglibproxy.Customer$$EnhancerByCGLIB$$2436ded2@73c6c3b2
我是媒婆,我要给你找对象,现在已经确认你的需求
开始物色
儿子要求:肤白貌美大长腿
OK的话,准备办事

3.静态代理和动态代理的区别:

1.静态代理通常只代理一个类,动态代理是代理一个接口下的多个实现类。

2.静态代理类事先知道要代理的是什么类,而动态代理类不知道要代理什么类,只有在运行时才知道。

3.静态代理只能通过手动完成代理操作,如果被代理类增加新的方法,代理类需要同步新增,违背开闭原则。

   动态代理采用在运行时动态生成代码的方式,取消了对被代理类的扩展限制,遵循开闭原则。

4.若动态代理要对目标类的增强逻辑扩展,结合策略模式,只需要新增策略类便可完成,无需修改代理类的代码。

4.代理模式的优缺点

优点:

1.代理模式能将代理对象与真实被调用的目标对象分离。

2.一定程度上降低了系统的耦合度,扩展性好。

3.可以起到保护目标对象的作用。

4.可以对目标对象的功能增强。

缺点:

1.代理模式会造成系统设计中类的数量增加。

2.在客户端和目标对象增加一个代理对象,会造成请求处理速度变慢。

3.增加了系统的复杂度。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不愿放下技术的小赵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值