设计模式学习-动态代理

代理模式

定义

给某一个对象提供一个代理,并由代理对象来控制对原对象的访问。

结构

  • Subject抽象主题角色。声明了真实主题和代理主题的共同接口,这样可以将代理主题取代真实主题,达到取代和控制的目的。
  • Proxy代理主题角色。包含了对真实主题的引用,同时控制这着对真实主题的访问,具有附加操作、控制访问的功能。
  • RealSubject真实主题。实现了抽象主题角色的接口,具有真正的业务功能。
    在这里插入图片描述

与装饰模式的区别

通过和装饰模式的类图对比可以发现,代理模式的类图和装饰模式的类图几乎完全一样,甚至代码结构都完全一样。它们最重要的区别在于

  • 装饰模式的思想在于对被装饰对象功能的扩展,比如给手机增加手机壳,没有改变手机的功能,但是更加美观。代理模式在与对被代理对象的完全控制,不光可以对功能进行扩展,更加控制着功能可不可以执行,比如常见的重要信息查询功能,可以通过代理模式对访问权限进行控制,并且增加记录日志功能。
  • 装饰模式中的装饰类只需要编写一个,可以接受任意构件;代理模式为每一个真实主题都要创建一个代理类,数量上要比装饰模式多很多。

示例

java中比较简单的实现代理模式的方法有两种,静态代理和jdk自带的proxy动态代理,用查询功能做示例。

package proxy.other;

public interface Searcher {

	void search(String userId);
}

package proxy.other;

public class ConcreteSearcher implements Searcher {

	@Override
	public void search(String userId) {
		System.out.println("查询订单列表");
	}

}

package proxy.other;

public class Log {

	public void log(String userId, Boolean success) {
		String result = success ? "成功" : "失败";
		System.out.println(userId + "查询订单列表" + result);
	}
}

package proxy.other;

public class LoginValidator {

	public boolean volidate(String userId) {
		if ("zhangsan".equals(userId)) {
			System.out.println("校验通过");
			return true;
		}
		System.out.println("校验失败");
		return false;
	}
}

静态代理

package proxy.staticproxy;

import proxy.other.ConcreteSearcher;
import proxy.other.Log;
import proxy.other.LoginValidator;
import proxy.other.Searcher;

public class StaticProxySearcher implements Searcher {

	private Searcher searcher = new ConcreteSearcher();

	private LoginValidator validator = new LoginValidator();

	private Log log = new Log();

	@Override
	public void search(String userId) {
		System.out.println(userId + "登陆");
		boolean success = Boolean.FALSE;
		if (validator.volidate(userId)) {
			searcher.search(userId);
			success = Boolean.TRUE;
		}
		log.log(userId, success);
	}

}

动态代理

package proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

import proxy.other.Log;
import proxy.other.LoginValidator;

public class DynamicProxy implements InvocationHandler {

	private Object target;

	private LoginValidator validator = new LoginValidator();

	private Log log = new Log();

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

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println(args[0] + "登陆");
		Object result = null;
		boolean success = Boolean.FALSE;
		if (validator.volidate((String) args[0])) {
			result = method.invoke(target, args);
			success = Boolean.TRUE;
		}
		log.log((String) args[0], success);
		return result;
	}

}

package proxy;

import java.lang.reflect.Proxy;

import proxy.other.ConcreteSearcher;
import proxy.other.Searcher;
import proxy.staticproxy.StaticProxySearcher;

public class Test {

	public static void main(String[] args) {
		System.out.println("静态代理");
		Searcher searcher = new StaticProxySearcher();
		searcher.search("lisi");
		System.out.println("----------------------------");
		System.out.println("动态代理");
		Searcher searcher2 = (Searcher) Proxy.newProxyInstance(Searcher.class.getClassLoader(),
				new Class[] { Searcher.class }, new DynamicProxy(new ConcreteSearcher()));
		searcher2.search("zhangsan");
	}
}

优点

  • 能够协调调用者和被调用者,在一定程度上降低了系统的耦合性,对于新增内容,无需修改源代码,只要新增代理类就可以,符合开闭原则。
  • 动态代理可以同时代理大量类,不需要编写新的代理类,对于相同功能的添加十分方便。

适用场景

  • 增加功能
  • 权限访问控制
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值