zoukankan      html  css  js  c++  java
  • 设计模式总结7--代理模式

    代理模式为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个
    客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间
    起到中介的作用

    代理模式一般涉及到三个角色
    抽象角色:声明真实对象和代理对象的共同接口;
    代理角色:代理对象角色内部含有对真实对象的引用,从而可以操
    作真实对象,同时代理对象提供与真实对象相同的接口以便在任何
    时刻都能代替真实对象。同时,代理对象可以在执行真实对象操
    作时,附加其他的操作,相当于对真实对象进行封装。
    真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。

    抽象角色

    public interface Subject {
    
        public void sales();
    }

    代理角色

    public class ProxySubject implements Subject{
    
        private Subject subject;
        public ProxySubject(Subject subject) {
            this.subject = subject;
        }
        
        
        @Override
        public void sales() {
            System.out.println("before");
            subject.sales();
            System.out.println("after");
        }
    }

    真实角色

    public class Dell implements Subject{
    
        @Override
        public void sales() {
            System.out.println("Dell sales");
        }
    
    }

    测试

    public class Test {
    
        public static void main(String[] args) {
            /* 买dell电脑找代理,传入真实对象*/
            ProxySubject proxy = new ProxySubject(new Dell());
            proxy.sales();
            
            
        }
    }

    ---------------------------------------------------------------
    ---------------------------------------------------------------
    动态代理:自动生成一个代理类
    第一种:使用Java内置的(必须实现某个接口,动态产生目标对象的实现类)
    第二种:使用一个库:cglib(动态产生一个目标对象的子类)

    第一种

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    public class MyHandler implements InvocationHandler {
    
        //被代理对象(目标对象)
        private Object target;
        public MyHandler(Object obj) {
            this.target = obj;
        }
        
        
        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            System.out.println("before advice");
            /*代表目标对象的某个方法执行 */
            Object result = method.invoke(target,args);
            System.out.println("after advice");
            return result;
        }
    
    }

    测试

    public class Test {
    
        public static void main(String[] args) {
            
            Dell dell = new Dell();
            MyHandler handler = new MyHandler(dell);
            /*代理对象要传入三个参数:目标对象的ClassLoader,目标对象实现了哪些接口 ,handler
                会返回一个实现了Subject接口的对象,并且它还代理了目标对象*/
                
            Subject subject = (Subject) Proxy.newProxyInstance(dell.getClass().getClassLoader(), dell.getClass().getInterfaces(), handler);
            subject.sales();
        
            
        }
    }

    有个缺点:就是必须实现某个接口
    Subject subject = (Subject) Proxy.newProxyInstance(dell.getClass().getClassLoader(), dell.getClass().getInterfaces(), handler);
    如果没有实现,而是拿真实角色来接受就会出错
    Dell dell = (Subject) Proxy.newProxyInstance(dell.getClass().getClassLoader(), dell.getClass().getInterfaces(), handler);

    延伸:
    当没有这个接口的时候要怎么实现代理呢。实际上就是用继承

    此时这个抽象角色已经不是接口了,而是一个类

    public class User {
    
        public void haha() {
            System.out.println("user haha");
        }
    }

    若要实现代理,用继承,然后就可以在执行的时候前置和后置可以写自己的,实际上这就是cglib
    的原理

    public class Son extends User{
    
        @Override
        public void haha() {
            System.out.println("xxxx");
            super.haha();
            System.out.println("xxxxx");
        }
    }

    第二种

    导入cglib-nodep-xxx.jar

    import java.lang.reflect.Method;
    
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    public class MyMethodInterceptor implements MethodInterceptor {
    
        @Override
        public Object intercept(Object obj, Method arg1, Object[] args,
                MethodProxy methodProxy) throws Throwable {
            System.out.println("前置通知");
            Object result = methodProxy.invokeSuper(obj, args);
            System.out.println("后置通知");
            
            return result;
        }
    
    }

    测试

    public class Test {
    
        public static void main(String[] args) {
            
            
            User user = new User();
            
            Enhancer enhancer = new Enhancer();
            /* 传入父类对象 */
            enhancer.setSuperclass(user.getClass());
            /* 传入MyMethodInterceptor,执行son的时候会自动执行里面的前置还有后置*/
            enhancer.setCallback(new MyMethodInterceptor());
            /* 动态产生user类的子类*/
            User son = (User) enhancer.create();
            son.haha();
            
        }
    }
  • 相关阅读:
    2021.1.28 个人rating赛补题报告
    2021.1.23 个人rating赛补题报告
    2021.1.23 个人rating赛补题报告
    2020.12.14 个人训练赛补题报告
    2020.11.28 2020团体程序设计天梯赛补题报告
    2020.12.3 Codeforces Beta Round #73(Div2)补题报告
    Xhorse VVDI Prog V5.0.6 is Ready for BCM2 Adapter
    Program 2021 Ford Bronco All Keys Lost using VVDI Key Tool Plus
    Xhorse VVDI Prog V5.0.4 Software Update in July 2021
    How to use Xhorse VVDI2 to Exchange BMW FEM/BDC Module?
  • 原文地址:https://www.cnblogs.com/itliucheng/p/4227106.html
Copyright © 2011-2022 走看看