• 结构型


    1、代理模式

    • 定义:

      给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。

      就好像房东想要出租房子,他让中介帮忙找租客,带看,签合同,房东只需要把房子挂出去表示出租就行了

     

    • 为什么要使用代理模式?

      • 中介隔离作用:

        • 在某些情况下,一个客户不想或者不能去直接访问真实角色,代理角色就能在中间起到一个桥梁连接的作用,前提条件是真实角色委托了代理角色,他们实现相同的接口,有共同的目标。

      • 开闭原则:

        • 代理角色还可以增加额外的功能,这样做我们只需要修改代理角色类而不需要再修改真实角色类,符合代码设计的开闭原则

        • 代理角色类主要负责为真实角色类【预处理消息、过滤消息、把消息转发给真实角色,以及事后对返回结果的处理等

        • 代理角色类本身并不真正实现服务,而是同过调用真实角色类的相关方法,来提供特定的服务。真正的业务功能还是由真实角色类来实现,但是可以在业务功能执行的前后加入一些公共的服务,如:缓存、日志这些功能,在代理角色类中编写,不用打开封装好的真实角色类。

     

    2、静态代理

    • 定义:

      静态代理是由程序员创建或特定工具自动生成源代码,在对其编译。在程序员运行之前,代理类.class文件就已经被创建了

    • 示例一:租房

       

      • Rent(租房事件)

        public interface Rent {
           public void rent();
        }
      • Host(房东:出租房子)

        public class Host implements Rent {
           public void rent() {
               System.out.println("房东出租房子!");
          }
        }
      • HousingAgency(房产中介:代理房东租房子)

        public class HousingAgency implements Rent {
           public Host host;

           ////通过构造方法实现房东与中介的委托代理
           public HousingAgency(Host host) {
               this.host = host;
          }

           public void rent() {
               host.rent();
               signContract();
               seeHouse();
               agencyFee();
          }

           public void signContract() {
               System.out.println("签合同");
          }

           public void seeHouse() {
               System.out.println("中介带看");
          }

           public void agencyFee() {
               System.out.println("中介收取中介费");
          }
        }
      • Tenant(租客:租房子)

        public class Tenant {

           public static void main(String[] args) {

               //实例化一个房东,生成委托对象
               Host host = new Host();
               //房产中介代理房东出租房子
               HousingAgency agency = new HousingAgency(host);
               /*
               租客通过中介租房子,中介也可以实现其他的功能
               输出结果:
              房东出租房子!
                   签合同
                   中介带看
                   中介收取中介费
               */
               agency.rent();

          }
        }
    • 示例二:使用静态代理实现日志功能

       

      • UserService

        public interface UserService {
           public void add();
           public void delete();
           public void update();
           public void query();
        }
      • UserServiceImpl

        public class UserServiceImpl implements UserService {
           public void add() {
               System.out.println("实现了add方法");
          }

           public void delete() {
               System.out.println("实现了delete方法");
          }

           public void update() {
               System.out.println("实现了update方法");
          }

           public void query() {
               System.out.println("实现了query方法");
          }
        }
      • UserServiceProxy

        public class UserServiceProxy implements UserService {

           private UserServiceImpl userService;

           //通过set方法实现userServiceImpl的委托代理
           public void setUserService(UserServiceImpl userService) {
               this.userService = userService;
          }

           public void add() {
               log("add");
               userService.add();
          }

           public void delete() {
               log("delete");
               userService.delete();
          }

           public void update() {
               log("update");
               userService.update();
          }

           public void query() {
               log("query");
               userService.query();
          }

           public void log(String msg) {
               System.out.println("[DEBUG] 调用了" + msg + "方法");
          }
        }
      • Client

        public class Client {
           public static void main(String[] args) {
               
               UserServiceImpl userService = new UserServiceImpl();
               UserServiceProxy proxy = new UserServiceProxy();
               proxy.setUserService(userService);
               
               /*
               输出结果:
              [DEBUG] 调用了add方法
        实现了add方法
               */
               proxy.add();
               /*
               输出结果:
              [DEBUG] 调用了query方法
        实现了query方法
               */
               proxy.query();
          }
        }
    • 优点:

      • 可以使真实角色的操作更加纯粹,不用去关注公共业务

      • 代理角色负责公共业务,分工更加明确

      • 公共业务发生扩展的时候,方便集中管理

    • 缺点:

      • 一个真实角色就会产生一个代理角色,代码量会增加,开发效率降低。

     

    3、动态代理

    • 定义:

      动态代理是在程序运行时通过反射机制动态创建的

    • 类别:

      • 基于接口的,JDK动态代理

        • Proxy

        • InvocationHandler

      • 基于类的

        • cglib

      • Java字节码实现

        • javaSsist

    • 示例一:租房

      • Rent

        public interface Rent {
           public void rent();
        }
      • Host

        public class Host implements Rent {
           public void rent() {
               System.out.println("房东出租房子!");
          }
        }
      • ProxyInvocationHandler(代理调用处理程序)

        //这是个可以自动生成代理类的类
        public class ProxyInvocationHandler implements InvocationHandler {

           //被代理的类
           private Rent rent;

           public void setRent(Rent rent) {
               this.rent = rent;
          }

           //生成代理类
           //第一个参数获得类加载器,
           //第二个参数获得被代理类的接口
           //第三个参数是InvocationHandler,因为这个类实现了InvocationHandler,所以可以是它本身
           public Object getProxy() {
               return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this);
          }

           //处理代理实例,并返回结果
           public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
               //用反射机制来实现动态代理的本质
               Object result = method.invoke(rent, args);
               signContract();
               seeHouse();
               agencyFee();
               return result;
          }

           public void signContract() {
               System.out.println("签合同");
          }

           public void seeHouse() {
               System.out.println("中介带看");
          }

           public void agencyFee() {
               System.out.println("中介收取中介费");
          }
        }
      • Tenant

        public class Tenant {
           public static void main(String[] args) {
             
               Host host = new Host();
               ProxyInvocationHandler proxyIH = new ProxyInvocationHandler();
               
               /*
               每个代理实例都有一个关联的调用处理程序,
               当在代理实例上调用方法时,方法调用将被编码并且分配到其调用处理程序的invoke方法。
               通过调用处理程序来处理我们要调用的接口对象
               */
               proxyIH.setRent(host);
               
               //动态生成代理角色
               Rent proxy = (Rent) proxyIH.getProxy();
               //代理角色去做业务
               proxy.rent();
          }
        }
    • 示例二:使用动态代理实现日志功能

      • UserService

        public interface UserService {
           
           public void add();
           public void delete();
           public void update();
           public void query();
        }
      • UserServiceImpl

        public class UserServiceImpl implements UserService {
           
           public void add() {
               System.out.println("实现了add方法");
          }

           public void delete() {
               System.out.println("实现了delete方法");
          }

           public void update() {
               System.out.println("实现了update方法");
          }

           public void query() {
               System.out.println("实现了query方法");
          }
        }
      • ProxyInvocationHandler

        //这是个可以自动生成代理类的工具类
        public class ProxyInvocationHandler implements InvocationHandler {

           //被代理的类
           private Object target;

           public void setTarget(Object target) {
               this.target = target;
          }

           //生成代理类
           //第一个参数获得类加载器,
           //第二个参数获得被代理类的接口
           //第三个参数是InvocationHandler,因为这个类实现了InvocationHandler,所以可以是它本身
           public Object getProxy() {
               return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
          }

           //处理代理实例,并返回结果
           public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
               //用反射来获取执行方法的名字
               log(method.getName());
               //用反射机制来实现动态代理的本质
               Object result = method.invoke(target, args);
               return result;
          }

           public void log(String msg) {
               System.out.println("[DEBUG] 执行了" + msg + "方法!");
          }
        }
      • Client

        public class Client {
           public static void main(String[] args) {
               //真实角色
               UserServiceImpl userService = new UserServiceImpl();

               ProxyInvocationHandler proxyIHandler = new ProxyInvocationHandler();
               //设置要代理的对象
               proxyIHandler.setTarget(userService);
               //动态生成代理类
               UserService proxy = (UserService) proxyIHandler.getProxy();
               proxy.delete();
          }
        }
    • 优点:

      • 可以使真实角色的操作更加纯粹,不用去关注公共业务

      • 代理角色负责公共业务,分工更加明确

      • 公共业务发生扩展的时候,方便集中管理

      • 一个动态代理类代理的是一个接口,一般对应的就是一类业务

      • 一个动态代理类可以代理多个实现了同一个接口的类

  • 相关阅读:
    WAP版浏览器不支持.NET的linkButton
    类型初始值设定项引发异常
    磁盘阵列卡
    SQL SERVER 存储过程的天然递归
    Jquery读取返回的JSON数据
    WebView.loadUrl()在真机环境中执行即报错的问题
    permission is only granted to system apps
    Android程序的版本检测与更新
    IE7下浮动(float)层不能实现环绕的问题
    性能优化的一知半解
  • 原文地址:https://www.cnblogs.com/LittleSkinny/p/13697051.html
Copyright © 2020-2023  润新知