首页 > 其他分享 >代理设计模式

代理设计模式

时间:2023-02-13 15:36:30浏览次数:35  
标签:System void 代理 Dog println 设计模式 public


代理设计模式

  • ​​1、代理设计模式​​
  • ​​1.1 静态代理模式​​
  • ​​1.2 动态代理模式​​

1、代理设计模式

  所谓代理,就是替别人完成一些事情。在Java开发中,我们也会遇到一些代理类的场景,这些代理类可以帮其他被代理类完成一些它没有或不方便完成的事情,而且还不会改变被代理类原来的功能。这样的场景有很多,如最常见的场景有权限过滤、添加日志、事务处理等。

  初学者可能会问为什么要多加个代理类,直接在原来类的方法中加上权限过滤等功能不也可以实现吗?这是因为程序设计中有一个类的单一性原则问题,这个原则很简单,就是每个类的功能尽可能高单一,类功能越单一,类被修改的可能性就越小。如果将权限判断放在被代理的业务类中,这个类就既要负责自己本身业务逻辑又要负责权限判断,那么就有两个因素会导致该类变化,如果权限规则一旦变化,那么这个类就必须得修改,这显然不是一个好的设计。另外,我们可能需要给多个被代理类加上同样的权限过滤,如果没有代理类,那么势必会出现大量冗余的代码。

  根据代理类的创建时机和创建方式的不同,可以将代理分为静态代理和动态代理

1.1 静态代理模式

  所谓静态代理模式,就是由开发人员在编译期间手动声明代理类并创建代理对象的模式。

  案例需求:需要在所有Dog接口实现类的所有实现方法执行之前加上一句"xx方法开始执行",执行之后加一句“xx方法执行完毕”,并要求不修改这些实现类的代码。

Dog接口代码:

public interface Dog {
void bark();
void run();
}

  Dog接口实现类TibetanMastiff(藏獒类)

public class TibetanMastiff implements Dog {
@Override
public void bark() {
System.out.println("藏獒在叫");
}

@Override
public void run() {
System.out.println("藏獒在跑");
}
}

  Dog接口实现类Huskie(哈士奇类)

public class Huskie implements Dog {
@Override
public void bark() {
System.out.println("哈士奇在叫");
}

@Override
public void run() {
System.out.println("哈士奇在跑");
}
}

  Dog接口代理类代码:

public class DogProxy implements Dog {

private Dog target;//实际被代理的对象

public DogProxy(Dog target) {
this.target = target;
}

public Dog getTarget() {
return target;
}

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

@Override
public void bark() {
System.out.println("bark方法开始执行");
target.bark();
System.out.println("bark方法执行结束");
}

@Override
public void run() {
System.out.println("run方法开始执行");
target.run();
System.out.println("run方法执行结束");
}
}

  测试类:

public class DogProxyTest {
public static void main(String[] args) {
DogProxy dp1 = new DogProxy(new TibetanMastiff());
dp1.bark();
dp1.run();

DogProxy dp2 = new DogProxy(new Huskie());
dp2.bark();
dp2.run();
}
}

代理设计模式_设计模式

  上述代码可以实现代理工作,但是代理类DogProxy只能给Dog一个借口实现代理工作,如果此时另一个接口的实现类也有相同的代理工作要求,则需要编写另一个代理类。

  另外关于Dog接口的两个抽象方法,其代理工作相同,所以代理类中就出现了重复的冗余代码。这也是不理想的。

1.2 动态代理模式

  所谓动态代理模式,就是代理类及代理类的对象都是在程序运行期间动态创建的,编译期间根本不存在的模式。

  ​​java.lang.reflect​​​包下提供了一个Proxy类和一个​​InvocationHandler​​接口,通过使用这个类和接口可以生成JDK动态代理类或动态代理对象。

  Proxy提供用于创建动态代理类和代理对象的静态方法,它也是所有动态代理类的父类。如果想要在程序中为一个或多个接口动态地生成实现类,那么就可以使用Proxy来创建动态代理类或它们的实例。

  • ​public static Class<?> getProxyClass(ClassLoader loader,Class<?>... interfaces)​​:创建一个动态代理类所对应的Class对象。
  • ​public static Object newProxyInstance(ClassLoader loader,Class<?>[] inferfaces,InvocationHandler h)​​:直接创建一个动态代理对象。第一个参数为被代理类的类加载器对象,第二个参数为被代理类实现的接口,第三个参数为代理类代理工作的处理器对象。

  ​InvocationHandler接口有一个​invoke​方法需要实现,该​invoke​方法中的三个参数分别为proxy,代表动态代理对象;method,代表正在执行的方法;args,代表执行代理对象的方法时传入的实参。

  案例需求:需要在所有的Dog、Person、Bird等接口的实现类的所有实现方法的方法执行之前加上一句"xx方法开始执行",执行之后加一句“xx方法执行完毕”,并要求不修改这些实现类的代码。

  动态代理要代理的接口1,Dog接口示例代码:

public interface Dog {
void bark();
void run();
}

  动态代理类要代理的接口2,Person接口示例代码:

public interface Person {
void study();
void think();
}

  动态代理要代理的接口3:Bird接口示例代码:

public interface Bird {
void jump();
void fly();
}

  Dog接口实现类示例代码:

public class TibetanMastiff implements Dog {
@Override
public void bark() {
System.out.println("藏獒在叫");
}

@Override
public void run() {
System.out.println("藏獒在跑");
}
}

  Person接口实现类代码

public class Chinese implements Person{
@Override
public void study() {
System.out.println("中国人在学习");
}

@Override
public void think() {
System.out.println("中国人在思考");
}
}

  Bird接口实现类代码

public class Magpie implements Bird {
@Override
public void jump() {
System.out.println("喜鹊在跳来跳去");
}

@Override
public void fly() {
System.out.println("喜鹊飞来了");
}
}

  代理类处理器必须事先​​Invocationhandler​​接口。

  代理类处理器MyInvocationHandler示例代码:

public class MyInvocationHandler implements InvocationHandler {
private Object target;

public MyInvocationHandler(Object target) {
super();
this.target = target;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method.getName()+"方法开始执行");
Object returnValue = method.invoke(target, args);
System.out.println(method.getName()+"方法执行结束");
return returnValue;
}
}

  动态代理测试类示例代码:

public class TestProxy {
public static void main(String[] args) {
TibetanMastiff tibetanMastiff = new TibetanMastiff();
MyInvocationHandler handler1 = new MyInvocationHandler(tibetanMastiff);
Dog dog = (Dog) Proxy.newProxyInstance(
tibetanMastiff.getClass().getClassLoader(),
tibetanMastiff.getClass().getInterfaces(),
handler1
);
dog.bark();
dog.run();

System.out.println("-------------");
Chinese chinese = new Chinese();
MyInvocationHandler handler2 = new MyInvocationHandler(chinese);
Person person = (Person) Proxy.newProxyInstance(
chinese.getClass().getClassLoader(),
chinese.getClass().getInterfaces(),
handler2
);
person.study();
person.think();

System.out.println("-------------");
Magpie magpie = new Magpie();
MyInvocationHandler handler3 = new MyInvocationHandler(magpie);
Bird bird = (Bird) Proxy.newProxyInstance(
magpie.getClass().getClassLoader(),
magpie.getClass().getInterfaces(),
handler3
);
bird.jump();
bird.fly();
}
}

代理设计模式_设计模式_02

  当动态代理对象需要代理一个或多个接口的方法时,实际上它所代理的方法体就是执行​​InvocationHandler​​​对象的​​invoke​​方法的执行体。使用动态代理可以非常灵活地实现解耦合,这种动态代理在Spring框架体系的AOP(Aspect Orient Program,即面向切面编程)中被称为AOP代理,AOP代理包含了目标对象的全部方法。但AOP代理中的方法与目标对象的方法存在差异,AOP代理中的方法可以在执行目标方法之前和之后插入一些通用处理。


标签:System,void,代理,Dog,println,设计模式,public
From: https://blog.51cto.com/u_15961549/6054229

相关文章

  • 什么是设计模式?
    所谓设计模式,就是对经常出现的软件设计问题的成熟解决方案。很多人把设计模式想象成非常高深的概念,实际上设计模式仅仅是对特定问题的一种惯性思维。有些人喜欢抱着一本设......
  • java动态代理技术
    ......
  • Solon2 开发之容器,八、动态代理的本质
    在Java里动态代理,主要分:接口动态代理和类动态代理。因为它的代理类都是动态创建的,所以名字里会带上“动态”。官网的有些地方叫“代理”,也有些地方叫“动态代理”。都......
  • spring动态代理
    动态代理publicinterfaceUserManager{voidaddUser(Stringusername);voiddelUser(Stringusername);}publicclassUserManagerImplimplementsUserMa......
  • 设计模式-简单工厂类
    简单工厂模式一个工厂类根据传入的参数,动态的决定去创建哪一个产品类。、前言介绍如果想要实现一个计算器功能,前台页面输入数字和运算符号,后台该如何去实现简单版本......
  • ipv6地名词:有状态(dhcpv6),无状态(slaac),前缀代理(pd)等解释
    ipv6地址获取有两种方式:路由器通告的前缀+自己编的后缀(无状态,stateless)DHCP给一个/128的地址(有状态,stateful)需要明确:无状态和有状态,仅仅指的是ipv6地址的获取方式。......
  • CSS架构之BEM设计模式
    为什么需要CSS架构?其实在日常开发CSS当中,会遇到许多的问题,使用设计模式能够很好的解决。例如在日常开发项目,需要组件化时,组件内部的class样式类管理就非常的杂乱。大部分......
  • 基于 Ubuntu 服务器配置原生的 Socks5 网关代理服务器
    常见的代理协议有http、https、socks4/5这三种,http协议的代理搭建方案最简单,但是http代理无法访问https网站,https代理无法实现调用远端dns,所以我个人推荐使用Scoks5协议......
  • 动态代理的相关知识点
    总所周知,两种通用代理:jdk动态代理、cglib代理jdk动态代理(java.lang.reflect.Proxyjava.lang.reflect.InvocationHandler)需要注意,jdk自带的代理只能为接口创建代理......
  • 前端设计模式:观察者与发布订阅模式
    观察者模式描述:观察者模式(ObserverPattern)由被观察者和观察者组成,观察者可以是多个,被观察者维护着多个观察者,如添加或删除观察者;当被观察着数据变化时,会通过广播的方式......