java设计模式之代理模式 (静态&动态)

  为其他对象提供一个代理控制对某个对象的访问,代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。

代理类和委托类要实现相同的接口,因为代理真正实现的还是委托类的方法。

使用场景:

  如果需要委托类处理某一业务,就可以在代理类中统一处理然后调用具体的实现类。

  主题接口:

/* 

        代理模式---------主题接口

 */

public interface Usermanager {

   public final String userId=null, userName=null;

   public void addUser(String userId, String userName);

   public void deluser(String userId);

   public String findUser (String userId);

   public void modifyUser(String userId, String userName);

 /*

  * 具体用户管理实现类

  */

public class UserManagerImpl implements Usermanager {

@Override

public void addUser(String userId, String userName) {

   System.out.println("UserManagerImpl.adduser");

}

 

@Override

public void deluser(String userId) {

System.out.println("UserManagerImpl.deluser");

}

 

@Override

public String findUser(String userId) {

System.out.println("UserManagerImpl.finduser");

return "张三";

}

 

@Override

public void modifyUser(String userId, String userName) {

System.out.println("UserManagerImpl.modifyUser");

}

}

 

/*

 * 代理类------用户管理实现类

 */

public class UserManagerImplProxy implements Usermanager {

// 目标对象

private Usermanager um;

 

// 通过构造方法传入对象

public UserManagerImplProxy(Usermanager um) {

this.um = um;

}

 

@Override

public void addUser(String userId, String userName) {

 

try {

// 添加日志打印功能

// 开始添加用户

System.out.println("start----------->adduser()");

um.addUser(userId, userName);

// 添加用户成功

System.out.println("success--------------->adduser()");

} catch (Exception e) {

// 添加用户失败

System.out.println("error------>adduser()");

}

}

 

@Override

public void deluser(String userId) {

um.deluser(userId);

}

 

@Override

public String findUser(String userId) {

um.findUser(userId);

return "张三";

}

 

@Override

public void modifyUser(String userId, String userName) {

um.modifyUser(userId, userName);

}

/*

 * 测试类

 */

public class Test {

public static void main(String[] args) {

Usermanager um = new UserManagerImplProxy(new UserManagerImpl());

um.addUser("04131146", "张三丰");

}

}

}

运行结果:

start----------->adduser()

UserManagerImpl.adduser

success--------------->adduser()

优点:

   编译期加入,提前指定谁调用谁,效率高。

缺点:

  1:静态代理很麻烦,需要大量的代理类。(当我们有多个目标对象需要代理时,就需要建立多个代理类)

 2:在编译期加入,系统的灵活性低。

  应用: 代理类可以对实现类进行统一的管理,如在实现具体之前,需要打印日志信息,这时只需添加一个静态代理,在代理类中添加打印功能,然后调用具体的实现类,这样就可以避免修改具体的实现类。

  引入动态代理:

   通过以上可以发现,每一个代理类只能为一个接口服务,这样程序开发中必然会产生许多代理类,此时可以使用一个代理类完成我那个全部的代理功能。。。

类结构:

 

package com.xiyou.dongtaidaili;

/* 代理模式

 * 主题接口

 */

public interface Usermanager {

   public final String userId=null, userName=null;

   public void addUser(String userId, String userName);

   public void deluser(String userId);

   public String findUser (String userId);

   public void modifyUser(String userId, String userName);

}

package com.xiyou.dongtaidaili;

 /*

  * 具体用户管理实现类 (实现 Usermanager接口)

  */

public class UserManagerImpl implements Usermanager {

@Override

public void addUser(String userId, String userName) {

   System.out.println("UserManagerImpl.adduser");

}

 

@Override

public void deluser(String userId) {

System.out.println("UserManagerImpl.deluser");

}

 

@Override

public String findUser(String userId) {

System.out.println("UserManagerImpl.finduser");

return "张三";

}

 

@Override

public void modifyUser(String userId, String userName) {

System.out.println("UserManagerImpl.modifyUser");

}

}

动态代理类:

/*

 * 代理类

 * 采用JDK动态代理必须实现InvocationHandler接口 使用Proxy 类创建相应的代理类 

 * InvocationHandler 是代理实例的调用处理程序实现的接口,

 * 每个代理类都具有一个关联的调用处理程序。

 * 对代理实例调用方法时,将对方调用进行编码并将其指派到它的调用处理程序的invoke()方法中。

 */

public class ProxyHandler implements InvocationHandler {

private Object target;

 

public Object newProxyInstance(Object target) {

this.target = target;

/*

 * newProxyInstance 返回一个指定接口的代理实例,该接口可以将方法代用指派到指定的调用处理程序。 loader -

 * 定义代理类的类加载器 interfaces - 代理类要实现的接口列表 h - 指派方法调用的调用处理程序

 */

return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);

}

/*

 * 反射 ,可以在不知道具体类的情下,根据配置的参数去调用一个类的方法, invoke(Object proxy, Method method,

 * Object[] args) 在代理实例上处理方法调用并返回结果 proxy 在其上调用方法的代理实例。

 * method:对应于在实例上处理的接口方法的Method实例。 arg:包含传入代理实例方法参数值的对应对象,

 * 返回:从代理实例的方法调用返回的值。

 */

@Override

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

System.out.println("satrt------>" + method.getName());

for (int i = 0; i < args.length; i++) {

System.out.println("args=" + args[i]);

}

Object ret = null;

try {

// 调用目标方法

ret = method.invoke(target, args);

System.out.println("sucess------>" + method.getName());

 

} catch (Exception e) {

System.out.println("error---------->" + method.getName());

throw e;

}

return ret;

}

 

}

测试类:

 

public class Client {

public static void main(String[] args) {

 ProxyHandler p = new ProxyHandler();

 Usermanager  usermanager =  (Usermanager) p.newProxyInstance(new UserManagerImpl());

     usermanager.addUser("04131145", "李四");

     System.out.println(usermanager.findUser("04131145"));

     System.out.println("client main =------>");

}

}

运行结果:

satrt------>addUser

args=04131145

args=李四

UserManagerImpl.adduser

sucess------>addUser

satrt------>findUser

args=04131145

UserManagerImpl.finduser

sucess------>findUser

张三

client main =------>

 AOP(面向切面编程):将日志,性能统计,安全控制,事件处理,异常处理等代码从业务逻辑代码中分离出来,通过这些行为的分离,我们希望可以将它们独立到非指导业务逻辑方法中,进而改变这些行为的时候不影响业务的逻辑的代码。

UserManagerImplProxy类中它的两个方法System.out.println("start-->addUser()")System.out.println("success-->addUser()"),这是做核心动作之前和之后的两个截取段,正是这两个截取段,却是我们AOP的基础,在OOP里,System.out.println("start-->addUser()")、核心动作、System.out.println("success-->addUser()")这个三个动作在多个类里始终在一起,但他们所要完成的逻辑却是不同的,如System.out.println("start-->addUser()")里做的可能是权限的判断,在所有类中它都是做权限判断,而在每个类里核心动作却各不相同,System.out.println("success-->addUser()")可能做的是日志,在所有类里它都做日志。正是因为在所有的类里,核心代码之前的操作和核心代码之后的操作都做的是同样的逻辑,因此我们需要将它们提取出来,单独分析,设计和编码,这就是我们的AOP思想。一句话说,AOP只是在对OOP的基础上进行进一步抽象,使我们的类的职责更加单一。

     总结:

代理对象就是被代理的对象包装一层,对齐内部做一些额外工作,比如用户无法访问外网,可以使用网络代理先翻墙,然后在访问外网。这就是代理的作用。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值