设计模式之代理模式

给某一个对象提供一个代理,并由代理对象控制对原对象的引用。代理模式的英文叫做Proxy, 它是一种对象结构型模式,代理模式分为静态代理和动态代理。

静态代理

使用场景:当你想对接口中的某个方法添加增强逻辑时可以有俩种选择。一是直接修改原方法,但这样违背了开闭原则“对扩展开放,对修改关闭”。第二种是使用静态代理。所谓静态代理就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前已经确定。静态代理的特点是委托类和代理类实现共同的接口。

举例:有个方法实现了”组团去北京“的逻辑,现在想在旅游完成后添加”拜访亲戚“的逻辑。

创建接口,实现组团去北京方法。

public interface IOrganizedTour {
    //组团去北京
    void travelToBeing();
}

旅行者类,实现接口

public class Traveller implements IOrganizedTour {
    @Override
    public void travelToBeing() {
        System.out.println("旅行社组织3天北京游-包吃包住");
    }
}

代理类,实现接口及方法增强

public class TravellerProxy implements IOrganizedTour {
    private Traveller travelCompany;

    public TravellerProxy(Traveller travelCompany) {
        this.travelCompany = travelCompany;
    }

    @Override
    public void travelToBeing() {
        travelCompany.travelToBeing();
        visitRelatives();
    }

    private void visitRelatives() {
        System.out.println("旅游后走访亲戚");
    }
}

调用测试类输出

public class MainTest {
    public static void main(String[] args) {
        Traveller travelCompany = new Traveller();
        TravellerProxy travelProxy = new TravellerProxy(travelCompany);
        travelProxy.travelToBeing();
    }
}
旅行社组织3天北京游-包吃包住
三天后拜访亲戚

 

动态代理

举例:

创建一个Person接口

public interface Person {
    void doSomething();
}

创建一个实现类

public class Bob implements Person {
  public void doSomething() {
    System.out.println("Bob doing something!");
  }
}

创建JDK动态代理类,使其实现InvocationHandler接口。拥有一个名为target的变量,并创建getTarget获取代理对象方法。

/**
* JDK动态代理
* 需要实现InvocationHandler接口
*/
public class JDKDynamicProxy implements InvocationHandler {
  //被代理的对象
  Person target;
  // JDKDynamicProxy构造函数
  public JDKDynamicProxy(Person person) {
    this.target = person;
  }
  // 获取代理对象
  public Person getTarget() {
    return (Person)Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
  }

  // 动态代理invoke方法
  public Person invoke(Object proxy, Method method, Object[] args) throws Throwable {
    // 被代理方法前执行
    System.out.println("JDKDynamicProxy do something before!");
    // 执行被代理的方法
    Person result = (Person) method.invoke(target, args);
    // 被代理方法后执行
    System.out.println("JDKDynamicProxy do something after!");
    return result;
  }
}

JDK动态代理测试类

public class JDKDynamicTest {
  public static void main(String[] args) {
    System.out.println("不使用代理类, 调用doSomething方法");
    Person person = new Bob();
    person.doSomething();
    System.out.println("-------------------------------------- 分割线 --------------------------------------");
    System.out.println("使用动态代理类, 调用doSomething方法");
    //获取代理类
    Person proxyPerson = new JDKDynamicProxy(new Bob()).getTarget();
    // 调用doSomething方法
    proxyPerson.doSomething();
  }
}

  

posted on 2020-10-02 21:36  lvguoliang(学无止境)  阅读(157)  评论(0)    收藏  举报