关于java代理模式的疑问 真实对象什么时候被创建
首先声明一点:尽管原对象和代理对象是"同一个类型",但是被代理的和原对象不是完全一样的对象,就好比说,原来的大厦叫河蟹大厦,现在我给大厦安装了电梯,但是他还叫河蟹大厦,我们代理之后的对象就是安了电梯的河蟹大厦,电梯没有用么?当然有用了,但是我们安装电梯后要不要使用原来河蟹大厦的功能比如,电灯呢?当然也要了!这就是代理之后和被代理之前的关系,代理当然是有用的啦!
当然你可能会说了:为什么不在设计之初就按上电梯呢?这个。。。很多时候我们是故意为之,当太多类似的函数的里面都需要同一条语句,并且位置都大致相似的时候,我们需要在每个函数里面都添加上么?一次两次还好,多次了你可能就会烦了。一句两句好,如果一下都是10几句,每个函数都一样的,就太“八股文”了。
下面是一个例子吧,算伪代码,只是想让你看看怎么用,不一定能直接运行。
proxy.newProxyInstance()生成的代理对象,是在传入InvocationHandler的对象基础之上“织入”的即改进的,所以你传入的这个对象必须new出来,要不然怎么对其进行改进呢?而一般来说,我们使用的是代理之后的类,而非原始类,代理之后的类可以对原始传入类的一些函数进行拓展,这就是动态代理的用途。
再具个例子吧。。。
我们有很多类,它们都执行不同的SQL语句来连接数据库。如果我们在每个类里面都在查询代码之前先连接数据库,之后关闭数据库连接,那会导致很多的代码重复,这时候如果我们利用代理就是这么一个效果。
public class MyHandler implements InvocationHandler
{
......被代理对象target传入,省略
.....
Object invoke(Object proxy,
Method method,
Object[] args)
{
..做链接数据库
Object obj = proxy.invoke(target,args);
..做关闭数据库
return obj;
}
}
然后执行的时候:
Query target = new Query();
Query advanceTarget = Proxy.newProxyInstance(target.getClass().getClassloader(),target.getClass().getInterfaces(),new MyHandler(target)) ;
上面的代码的意思能看懂吧?
Handler相当于一张标准网,他通过传入target,把它增强为能自动连接数据库,查询完毕后能关闭数据库。
Proxy new的时候,使用“这张网”来增强target,并返回增强之后的数据库,我们之后使用advancdTarget就可以无忧无虑的了!因为不用再考虑关闭数据库和打开数据库这些繁琐的细节了。
以上都是AOP的概念,如果有兴趣可以读读Spring框架的书就能更深刻的理解意思了。希望我写的你都能明白,呵呵。
=========================================================
上次的解答:
首先给你一段代码,其他的代码看完了解释。
// 抽象角色:
abstract public class Subject {
abstract public void request();
}
// 真实角色:实现了Subject的request()方法。
public class RealSubject extends Subject {
public RealSubject() {
}
public void request() {
System.out.println( " From real subject. " );
}
}
// 代理角色:
public class ProxySubject extends Subject {
private RealSubject realSubject; // 以真实角色作为代理角色的属性
public ProxySubject() {
}
public void request() { // 该方法封装了真实对象的request方法
preRequest();
if ( realSubject == null ) {
realSubject = new RealSubject();
}
realSubject.request(); // 此处执行真实对象的request方法
postRequest();
}
private void preRequest() {
// something you want to do before requesting
}
private void postRequest() {
// something you want to do after requesting
}
}
// 客户端调用:
Subject sub = new ProxySubject();
Sub.request();
开始解释,上面看到了,其实正如你说的,如果只是简单的为了Client调用原对象,大可不必这么费尽周折啊!
使用代理的意义是:
1、当某些对象不方便直接调用某对象的时候,多数情况是团队开发中,抽象出接口了,但是实现类还没有出来。所以就使用代理了
2、这种情况更有用:为了让被代理类加强功能,不知道你有没有使用过Spring、Struts等框架,这些框架中经常有“代理”、“织入”等AOP的概念,简单的说就是:你原来有一个人的类,只能吃饭,我现在通过代理,给这个人的类加上了喝水、说话的功能,代理的设计模式就实现了这种静态代理。
注意,这和包装等是不一样的。因为代理类和被代理类有相同的父接口。
以上都是我自己写的解释,水平有限,希望和你继续探讨~