文档章节

代理模式-结构型模式1

凯文加内特
 凯文加内特
发布于 2014/02/13 17:42
字数 1223
阅读 142
收藏 8

即Proxy Pattern,23种java常用设计模式之一。代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

定义:

为其他对象提供一种代理以控制对这个对象的访问。

结构:

说明:

Proxy:代理对象,通常具有如下功能:

实现与具体的目标对象一样的接口,这样就可以使用代理来代替具体的目标对象

保存一个指向具体目标对象的引用,可以在需要的时候调用具体的目标对象

可以控制对具体目标对象的访问,并可能负责创建和删除它

Subject:目标接口,定义代理和具体目标对象的接口,这样就可以在任何使用具体目标对象的地方使用代理对象

RealSubject:具体的目标对象,真正实现目标接口要求的功能。

具体代码:

/**
 * 抽象的目标接口,定义具体的目标对象和代理公用的接口
 */
public interface Subject {
	/**
	 * 示意方法:一个抽象的请求方法
	 */
	public void request();
}

/**
 * 具体的目标对象,是真正被代理的对象
 */
public class RealSubject implements Subject {

	public void request() {
		//执行具体的功能处理
	}

}

/**
 * 代理对象
 */
public class Proxy implements Subject {
	/**
	 * 持有被代理的具体的目标对象
	 */
	private RealSubject realSubject = null;

	/**
	 * 构造方法,传入被代理的具体的目标对象
	 * @param realSubject 被代理的具体的目标对象
	 */
	public Proxy(RealSubject realSubject) {
		this.realSubject = realSubject;
	}

	public void request() {
		//在转调具体的目标对象前,可以执行一些功能处理

		//转调具体的目标对象的方法
		realSubject.request();

		//在转调具体的目标对象后,可以执行一些功能处理
	}

}


代理(Proxy)有两种:

静态代理-Static proxy

动态代理-Dynamic proxy

具体案例:

1. 静态代理

为实现静态代理需要为HelloSpeaker写一个HelloProxy类,同样实现IHello接口,并在hello方法执行log,并执行HelloSpeaker的hello()方法。

/**
 * 此处可以为接口也可以为抽象类
 * @author ljn
 *
 */
public interface IHelloSpeaker {
	public abstract void hello();
}

/**
 * 接口实现类日志功能  简单的打印一句话
 * @author ljn
 *
 */
public class HelloSpeaker implements IHelloSpeaker {
	public void hello(){
		System.out.println("............this is Log");
	}
}

/**
 * 代理类实现IHelloSpeaker接口,同时拥有实际对象的引用(private HelloSpeaker helloObj;//代理类内部引用真实类)
 * 代理必须完成委托对象的动作,也可以添加自己的动作(doBefore,doAfter)。
 * 
 * @author ljn
 * 
 */
public class HelloProxy implements IHelloSpeaker {

	private HelloSpeaker helloObj;// 代理类内部引用委托类

	public HelloProxy(HelloSpeaker helloSpeaker) {
		this.helloObj = helloSpeaker;
	}

	private void doBefore() {
		System.out.println("method doBefore invoke!");
	}

	private void doAfter() {
		System.out.println("method doAfter invoke!");

	}

	@Override
	public void hello() {
		// TODO Auto-generated method stub
		doBefore();// 其他业务逻辑
		helloObj = new HelloSpeaker();
		helloObj.hello();// 委托类具体的业务逻辑。
		doAfter();// 其他业务逻辑
	}
}
/**
*测试类
*/
public class Test {
	public static void main(String[] args) {
//其中HelloProxy中helloObject为需要代理的对象,在其它地方如下来使用代理机制
		IHelloSpeaker proxy = new HelloProxy(new HelloSpeaker());
		proxy.hello();
	}
}

2:动态代理:

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

public class LogHandler implements InvocationHandler { 
    
    private Object delegate;

    public Object bind(Object delegate) { 
        this.delegate = delegate; 
        return Proxy.newProxyInstance( 
                           delegate.getClass().getClassLoader(), 
                           delegate.getClass().getInterfaces(), 
                           this); 
    }

	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		Object result = null;         
        try { 
            System.out.println("method starts..."+method);
            result = method.invoke(delegate, args);
            System.out.println("method starts..."+method);
        } catch (Exception e){ 
            e.printStackTrace();
        }        
        return result; 
	}
}
//测试程序
public static void main(String[] args) {
        LogHandler logHandler  = new LogHandler(); 
        
        IHelloSpeaker helloProxy = 
                (IHelloSpeaker) logHandler.bind(new HelloSpeaker()); 
        helloProxy.hello();
    }

使用场景:

当客户端代码需要调用某个对象时,客户端实际上也不关心是否准确得到该对象,它只要一个能提供该功能的对象即可,此时我们就可返回该对象的代理(Proxy)。

      实际用例:

看到此处,相信读者应该对Spring的AOP框架有点感觉了:当Spring容器中的被代理Bean实现了一个或多个接口时,Spring所创建的AOP代理就是这种动态代理。Spring AOP与此示例应用的区别在哪里呢?Spring AOP更灵活,当Sping定义InvocationHandler类的invoke()时,它并没有以硬编码方式决定调用哪些拦截器,而是通过配置文件来决定在invoke()方法中要调用哪些拦截器,这就实现了更彻底的解耦——当程序需要为目标对象扩展新功能时,根本无须改变Java代理,只需要在配置文件中增加更多的拦截器配置即可。

优点和缺点:

1) 优点: 向客户端隐藏了访问某个对象的细节及复杂性;可以动态地调用一个对象中的方法,且无需实现固定的接口。

留给自己的问题:

spring的aop,hibernate,mybatis的懒加载应用代理模式

本文转载自:http://bbs.csdn.net/topics/390199476

上一篇: 范式
下一篇: Spring原理概述
凯文加内特
粉丝 341
博文 701
码字总数 110786
作品 0
青岛
后端工程师
私信 提问
设计模式的学习(7)适配器模式

适配器模式 适配器模式(Adapter Pattern)将一个接口转换成客户希望的另一个接口,使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。 适配器模式既可以作为类结构型模式,也可以作...

杨健-YJ
2018/12/27
44
0
PHP设计模式(一):简介及创建型模式

我们分三篇文章来总结一下设计模式在PHP中的应用,这是第一篇创建型模式。 一、设计模式简介 首先我们来认识一下什么是设计模式: 设计模式是一套被反复使用、容易被他人理解的、可靠的代码设...

juhenj
2014/05/15
285
2
设计模式梳理(一)

设计模式梳理(一) 总体来说设计模式分为三大类: @案例源码地址:https://gitlab.com/lxqxsyu/DisgnPattern 创建型模式 简单工厂模式 工厂类是整个模式的关键。它包含必要的判断逻辑,能够...

lxq_xsyu
2017/11/02
0
0
小菜学设计模式——设计模式总结之创建型

1、面向过程与面向对象 1)面向过程通过划分功能模块,通过函数间相互调用来实现,但需求变化时就需要更改函数,而你改动的函数有多少地方在调用她呢?关联多少数据,这是很不容易弄得清楚地...

learn_more
2015/07/05
180
0
【软考学习】设计模式——状态模式

【背景】 设计模式是非常重要的一块知识,每个设计模式都值得深入了解和学习。 【内容】 结构型设计模式总结: 状态设计模式总结: 一、定义:当一个对象的内在状态改变时允许改变其行为,这...

yym15732626210
2018/01/31
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Mybatis Plus删除

/** @author beth @data 2019-10-17 00:30 */ @RunWith(SpringRunner.class) @SpringBootTest public class DeleteTest { @Autowired private UserInfoMapper userInfoMapper; /** 根据id删除......

一个yuanbeth
今天
4
0
总结

一、设计模式 简单工厂:一个简单而且比较杂的工厂,可以创建任何对象给你 复杂工厂:先创建一种基础类型的工厂接口,然后各自集成实现这个接口,但是每个工厂都是这个基础类的扩展分类,spr...

BobwithB
今天
5
0
java内存模型

前言 Java作为一种面向对象的,跨平台语言,其对象、内存等一直是比较难的知识点。而且很多概念的名称看起来又那么相似,很多人会傻傻分不清楚。比如本文我们要讨论的JVM内存结构、Java内存模...

ls_cherish
今天
4
0
友元函数强制转换

友元函数强制转换 p522

天王盖地虎626
昨天
5
0
js中实现页面跳转(返回前一页、后一页)

本文转载于:专业的前端网站➸js中实现页面跳转(返回前一页、后一页) 一:JS 重载页面,本地刷新,返回上一页 复制代码代码如下: <a href="javascript:history.go(-1)">返回上一页</a> <a h...

前端老手
昨天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部