zoukankan      html  css  js  c++  java
  • 【设计模式】代理模式-Proxy

    转载:https://www.cnblogs.com/yangchongxing/p/7654725.html

    代理模式定义如下:

    Provide a surrogate or placeholder for another object to control access to it。为另一个对象提供一个代理或占位符以控制对它的访问。

    代理模式使用非常广泛,理解代理模式对解决实际问题大有裨益的。使用代理模式必须让代理类和目标类实现相同的接口。

    我们以添加用户业务为例

    // 用户接口
    package com.ycx.pattern.proxy;
    public interface UserService {
        public void insertUser();
    }
    // 用户实现类
    package com.ycx.pattern.proxy;
    public class UserServiceImpl implements UserService {
        @Override
        public void insertUser() {
            System.out.println("添加用户...");
        }
    }

    我们若要添加一个用户信息,需要new一个UserServiceImpl实例对象,然后调用insertUser方法。代码如下:

    // 客户端
    package com.ycx.pattern.proxy;
    public class Client {
        public static void main(String[] args) {
            UserService userServie = new UserServiceImpl();
            userServie.insertUser();
        }
    }

    执行结果
    添加用户...

    静态代理

    若这时新添一个业务,添加用户要在insertUser方法的开始和结束追加日志,其他地方没有这个业务,所以添加用户的业务不能修改,这种情况可以使用代理实现。代码如下:

    // 代理
    package com.ycx.pattern.proxy;
    public class UserServiceProxy implements UserService {
        private UserService _userService;
        public UserServiceProxy(UserService userService) {
            _userService = userService;
        }
        @Override
        public void insertUser() {
            // 开始日志
            System.out.println("开始");
            _userService.insertUser();
            // 结束日志
            System.out.println("结束");
        }
    }
    // 客户端
    package com.ycx.pattern.proxy;
    public class Client {
        public static void main(String[] args) {
            //  创建代理
            UserServiceProxy proxy = new UserServiceProxy(new UserServiceImpl());
            proxy.insertUser();
        }
    }

    执行结果
    开始
    添加用户...
    结束

    上边的代理是比较随便的,只要实现了用户接口,都可以,再看看使用指定代理,这样代理就必须是制定的。代码如下:

    // 接口
    package com.ycx.pattern.proxy;
    public interface UserService {
        public void insertUser();
        public UserService getProxy();
    }
    // 实现类
    package com.ycx.pattern.proxy;
    public class UserServiceImpl implements UserService {
        private UserServiceProxy proxy = null;
        @Override
        public void insertUser() {
            // 关键代码是判断是不是自己指定的代理
            if (!isProxy()) {
                System.out.println("请使用指定的代理");
            } else {
                System.out.println("添加用户...");
            }
        }
        // 关键代码判断代理
        private boolean isProxy() {
            return this.proxy == null ? false : true;
        }
        // 关键代码返回自己的代理
        @Override
        public UserService getProxy() {
            this.proxy = new UserServiceProxy(this);
            return this.proxy;
        }
    }
    // 代理
    package com.ycx.pattern.proxy;
    public class UserServiceProxy implements UserService {
        private UserService _userService;
        public UserServiceProxy(UserService userService) {
            _userService = userService;
        }
        @Override
        public void insertUser() {
            System.out.println("开始");
            _userService.insertUser();
            System.out.println("结束");
        }
        @Override
        public UserService getProxy() {
            return this;
        }
    }
    // 客户端
    package com.ycx.pattern.proxy;
    public class Clicent {
        public static void main(String[] args) {
            // 只有使用自的代理才可以
            UserService proxy = new UserServiceImpl().getProxy();
            proxy.insertUser();
        }
    }

    执行结果
    开始
    添加用户...
    结束

    我们来直接new一个对象执行,或者new一个代理,验证结果。代码如下:

    // 客户端
    package com.ycx.pattern.proxy;
    public class Client {
        public static void main(String[] args) {
            // 直接new一个对象
            new UserServiceImpl().insertUser();
        }
    }
    

    执行结果
    请使用制定的代理

    // 客户端
    package com.ycx.pattern.proxy;
    public class Client {
        public static void main(String[] args) {
            // 直接new一个代理
            UserServiceProxy proxy = new UserServiceProxy(new UserServiceImpl());
            proxy.insertUser();
        }
    }

    执行结果
    开始
    请使用制定的代理
    结束

    从上面看都是不行的,只能使用指定的代理才可以。

    下面是重头戏

    动态代理-即面向横切面编程AOP(Aspect Oriented Programming)
    InvocationHandler 是JDK提供的动态代理接口。Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。

    还是上面的例子,用动态代理实现代码如下:

    // 动态代理
    package com.ycx.pattern.proxy;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    public class MyInvocationHandler implements InvocationHandler {
        private Object object;
        MyInvocationHandler(Object object) {
            this.object = object;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("开始");
            Object result = method.invoke(object, args);
            System.out.println("结束");
            return result;
        }
    }
    // 客户端
    package com.ycx.pattern.proxy;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Proxy;
    public class Client {
        public static void main(String[] args) {
            InvocationHandler h = new MyInvocationHandler(new UserServiceImpl());
            // 使用Proxy获得实例
            UserService proxy = (UserService) Proxy.newProxyInstance(UserService.class.getClassLoader(), new Class[]{UserService.class}, h);
            proxy.insertUser();
        }
    }

    上面的实现方式客户端使用起来不方便,可以定义一个专门的客户代理。代码如下:

    // 动态代理
    package com.ycx.pattern.proxy;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    public class MyInvocationHandler implements InvocationHandler {
        private Object object;
        MyInvocationHandler(Object object) {
            this.object = object;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("开始");
            Object result = method.invoke(object, args);
            System.out.println("结束");
            return result;
        }
    }
    // 客户代理
    package com.ycx.pattern.proxy;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Proxy;
    public class DynamicProxy {
        @SuppressWarnings("unchecked")
        public static <T> T newProxyInstance(T instance) {
            ClassLoader loader = instance.getClass().getClassLoader();
            Class<?>[] interfaces = instance.getClass().getInterfaces();
            InvocationHandler h = new MyInvocationHandler(instance);
            return (T) Proxy.newProxyInstance(loader, interfaces, h);
        }
    }
    // 客户端
    package com.ycx.pattern.proxy;
    public class Client {
        public static void main(String[] args) {
            // 使用定制的代理返回实例
            UserService proxy = DynamicProxy.newProxyInstance(new UserServiceImpl());
            proxy.insertUser();
        }
    }

     待续...

  • 相关阅读:
    毕业设计-1.11
    毕业设计-1.10
    毕业设计-1.09
    毕业设计-1.08
    毕业设计-1.07
    [工具]Maven的安装和配置【MyEclipse】
    毕业设计-1.06
    tomcat部署项目时省略项目名
    Jenkins实现iOS项目自动化打包(含踩坑记录)
    钉钉小程序封装网络请求
  • 原文地址:https://www.cnblogs.com/yangchongxing/p/7654725.html
Copyright © 2011-2022 走看看