设计模式之代理模式

        在某些情况下,客户端代码不想或不能够直接调用被调用者,代理对象可以在客户端和目标对象之间起到中介的作用。这种情况下,客户端实际上也不关心是否准确得到该对象,它只要一个能够提供该功能的对象即可,此时就可返回对象的代理。代理可以理解为一个对象代表另一个对象来采取行动。对客户端而言,它不能分辨出代理对象与真实对象的区别,它也无须分辨代理对象和真实对象的区别。客户端的代码并不知道真正的被代理对象,客户端代码面向接口编程,它仅仅持有一个被代理对象的接口。简单来说:代理模式就是为另一个对象提供一个替身或占位符以控制对这个对象的访问。

1.适用性和优缺点
1.适用性
a.远程代理为一个对象在不同的地址空间提供局部代表
b.虚代理根据需要创建开销很大的对象。
c.保护代理控制对原始对象的访问。
d.智能指引取代了简单的指针,它在访问对象时执行一些附加操作。

2.优点
a.职责清晰
b.高扩展性
c.智能化

3.缺点
a.客户端与真实主题间增加了代理对象,造成请求处理速度变慢。
b.需要额外工作。

2.示例讲解
        我们今天讲代理分两方面举例子,一个是静态代理,另一个是动态代理。
1.静态代理
首先定义一个目标对象接口
public interface Object {

    void action();
}
目标类实现
public class ObjectImpl implements Object {

    public void action() {
        System.out.println("========");
        System.out.println("========");
        System.out.println("这是被代理的类");
        System.out.println("========");
        System.out.println("========");
    }
}
接着就是代理的出现。
public class ProxyObject implements Object {

    Object obj;
    
    public ProxyObject() {
        System.out.println("这是代理类");
        obj = new ObjectImpl();
    }
    
    public void action() {
        System.out.println("代理开始");
        obj.action();
        System.out.println("代理结束");
    }
}
客户端程序
public class Test {

    public static void main() {
    	Object obj = new ProxyObject();
        obj.action();
    }
}
运行结果
这是代理类
代理开始
========
========
这是被代理的类
========
========
代理结束
        这就是静态代理,由客户端代码可知,代理模式中客户端并不知道目标对象的具体信息,只是通过调用目标对象的代理,一般真实目标对象只会隐藏在代理类中,然后代理类的方法将封装真实对象的方法。

2.动态代理(借助于Java本身提供的特性)
首先定义目标接口
public interface Dog
{
	// info()方法声明
	void info();
	// run()方法声明
	void run();
}
目标类的实现
public class GunDog implements Dog
{
	//info方法实现,仅仅打印一个字符串
	public void info()
	{
		System.out.println("我是一只猎狗");
	}
	//run方法实现,仅仅打印一个字符串
	public void run()
	{
		System.out.println("我奔跑迅速");
	}
}
提供一个拦截器,便于在执行目标方法前、后进行增强处理。
public class TxUtil
{
	// 第一个拦截器方法:模拟事务开始
	public void beginTx()
	{
		System.out.println("=====模拟开始事务=====");
	}
	// 第二个拦截器方法:模拟事务结束
	public void endTx()
	{
		System.out.println("=====模拟结束事务=====");
	}
}
实现系统提供的InvocationHandler接口,该实现类的invoke方法将会作为代理对象的方法实现,是通过反射回调被代理对象的目标方法。
import java.lang.reflect.*;
public class MyInvokationHandler
	implements InvocationHandler
{
	// 需要被代理的对象
	private Object target;
	public void setTarget(Object target)
	{
		this.target = target;
	}
	// 执行动态代理对象的所有方法时,都会被替换成执行如下的invoke方法
	public Object invoke(Object proxy, Method method, Object[] args)
		throws Exception
	{
		TxUtil tx = new TxUtil();
		// 执行TxUtil对象中的beginTx()。
		tx.beginTx();
		// 以target作为主调来执行method方法
		Object result = method.invoke(target , args);
		// 执行TxUtil对象中的endTx()。
		tx.endTx();
		return result;
	}
}
生成动态代理
import java.lang.reflect.*;
public class MyProxyFactory
{
	// 为指定target生成动态代理对象
	public static Object getProxy(Object target)
		throws Exception
	{
		// 创建一个MyInvokationHandler对象
		MyInvokationHandler handler = new MyInvokationHandler();
		// 为MyInvokationHandler设置target对象
		handler.setTarget(target);
		// 创建、并返回一个动态代理
		return Proxy.newProxyInstance(target.getClass().getClassLoader()
			, target.getClass().getInterfaces(), handler);
	}
}


客户端程序:
public class Test
{
	public static void main(String[] args)
		throws Exception
	{
		// 创建一个原始的GunDog对象,作为target
		Dog target = new GunDog();
		// 以指定的target来创建动态代理
		Dog dog = (Dog)MyProxyFactory.getProxy(target);
		// 调用代理对象的info()和run()方法
		dog.info();
		dog.run();
	}
}
运行结果
=====模拟开始事务=====
我是一只猎狗
=====模拟结束事务=====
=====模拟开始事务=====
我奔跑迅速
=====模拟结束事务=====
        从动态代理可以看出,代理可以对目标执行方法进行增强处理。
        Spring的AOP代理就是动态代理,如果加入容器的目标对象有实现接口,用JDK代理如果目标对象没有实现接口,用Cglib代理。

3.代理模式与其它几种模式
1.代理模式与装饰者模式:两者都提供间接访问对象层。都保存被调用的引用。但是代理模式是用一个对象代表另一个控制对象访问,而装饰者模式是动态地给组件对象增加职能。

2.代理模式、适配器模式:代理模式和适配器模式应该说很相像,但是他们的区别也很明显,代理模式和被代理者的接口是同一个,只是使用中客户访问不到被代理者,所以利用代理进行间接的访问,而适配器模式,是因为接口不同,为了让用户使用到统一的接口,把原先的对象通过适配器让用户统一的使用,大多数运用在代码维护的后期,或者借用第三方库的情况下 。













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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值