【设计模式】-代理模式

译文

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

代理模式的结构和uml类图

  1. 抽象主题(Subject)
  2. 实际主题(RealSubject)
  3. 代理(Proxy)

在这里插入图片描述

类图的解释

实际主题和主题的代理对象都实现抽象主题接口,同时主题的代理对象维护一个对实际主题的引用 这样的话用户就可以直接使用主题的代理对象完成业务逻辑 然后主题的代理对象在不改变主题的基础上可以对主题的进行控制

一个通俗易懂的例子

通俗理解就是主题和代理主题就是老板和小秘书,一般的电话都是小秘书接听的 小秘书自行判断是否需要让老板接电话 然后还可以在老板接听完电话之后帮助老板整理一下

uml类图

在这里插入图片描述

代码实现

public interface Human {
  void healPhone();
}
public class Boss implements Human{
  @Override
  public void healPhone() {
    System.out.println("我是老板 你干嘛啊");
  }
}
public class Secretary  implements Human{
  private Boss boss;

  public Secretary(Boss boss) {
    this.boss = boss;
  }

  @Override
  public void healPhone() {
    System.out.println("我是秘书 我们先唠会嗑");
    boss.healPhone();
    System.out.println("可怜的秘书 开始整理材料");
  }
}
public class Test {
  public static void main(String[] args) {
    Secretary secretary=new Secretary(new Boss());
    secretary.healPhone();
  }
}

在这里插入图片描述

基于jdk的代理

同样是上面的例子 我们用jdk提供的动态代理试试

在上面我们写了秘书类 但是这里我们就不用写这个类了

public class SecretaryFactory implements InvocationHandler {

  private Human target;
  public SecretaryFactory() {
    target=new Boss();
  }
  Object getInstance(){    //返回一个主题的代理对象 就是秘书 因为jdk替我们实现了这个功能 我们就没必要写一个秘书类了
    return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
  }

  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.println("我是秘书 我们先唠会嗑");
    Object invoke = method.invoke(target,args);
    System.out.println("可怜的秘书 开始整理材料");
    return invoke;
  }
}
public class Test {
  public static void main(String[] args) {
    SecretaryFactory secretaryFactory =new SecretaryFactory();
    Human instance = (Human) secretaryFactory.getInstance();
    instance.healPhone();
  }
}

在这里插入图片描述

简单的aop实现

  1. 创建一个maven工程
  2. 添加xml文件(自己定义的)
  3. 导包dom4j解析xml
  4. 编写简单的接口和实现类
  5. 编写进行增强的方法
  6. 编写代理类(基于jdk)
  7. 编写测试类

添加依赖

 <dependencies>
        <dependency>
            <groupId>org.dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>2.1.1</version>
        </dependency>
    </dependencies>

添加xml文件(自己定义的)

<?xml version="1.0" encoding="UTF-8"?>
<proxys>
    <proxy id="MyProxy" class="com.yxx.CalcImp">
        <method name="add">
            <prefix bean="com.yxx.SendMessage" mtd="preAdd" />
            <suffix bean="com.yxx.SendMessage" mtd="afterAdd" />
        </method>
    </proxy>
</proxys>

编写简单的接口和实现类

public interface Calc {
  void add();
}


public class CalcImp implements Calc{
  @Override
  public void add() {
    System.out.println("正在执行加法运算");
  }
}

编写进行增强的方法

public class SendMessage{
  public void preAdd() {
    System.out.println("加法计算之前");
  }

  public void afterAdd() {
    System.out.println("加法运算之后");
  }
}

编写代理类(基于jdk)

package com.yxx;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @Author: YuXinXin
 * @Description:
 * @Date:Created in 9:06 2020/12/31
 **/
public class MyProxy  implements InvocationHandler {

  public Class target;
  Element myProxy;

  public  Object getProxy(String id) {
    try {
      File f = new File("src/main/resources/1.xml");
      Document doc = new SAXReader().read(f);
      Element root = doc.getRootElement();//xml的根节点
      for (Element element : root.elements()) {
        if(element.attributeValue("id").equals(id)){ //找到用户需要的代理
          myProxy= element;
          String proxyClass=myProxy.attributeValue("class");
          target=Class.forName(proxyClass); //获得类
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
    return Proxy.newProxyInstance(target.getClassLoader(),target.getInterfaces(),this);//创建代理对象
  }



  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    Element myMethod = myProxy.elements().get(0);
    String methodName=myMethod.attributeValue("name");
    if(method.getName().equals(methodName)){
      String bean1 = myMethod.elements().get(0).attributeValue("bean");
      String mtd1 = myMethod.elements().get(0).attributeValue("mtd");
      String bean2 = myMethod.elements().get(1).attributeValue("bean");
      String mtd2 = myMethod.elements().get(1).attributeValue("mtd");


      //方法开始前增强
      Object obj1 = Class.forName(bean1).newInstance();
      Method method1 = obj1.getClass().getDeclaredMethod(mtd1);
      method1.invoke(obj1);

      //执行方法
      method.invoke(target.newInstance(),args);

      //方法开始之后增强方法
      Object obj2 = Class.forName(bean2).newInstance();
      Method method2 = obj2.getClass().getDeclaredMethod(mtd2);
      method2.invoke(obj2);
    }
    return null;
  }
}

编写测试类

public class Text {
  public static void main(String[] args) {
    Calc calc=(Calc)new MyProxy().getProxy("MyProxy");
    calc.add();
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值