呵呵,banq,我昨天仔细想了好久,关于这个Bob的dynamic proxy方法,我唯一不喜欢的就是它要求用户使用stupid cast,也就是说,从Line到Subject之间的cast。
这很不安全,万一用户不小心从一个没有经过proxy的原始Line对象cast到Subject,就会出问题。
而这里,问题的关键,还是Java语言不支持静态的proxy(比如类似上面一个帖子中的C++的mixin)。
假如,Java语言能够支持一个delegate model,比如:
一个connection pool的示例代码(一般都用dynamic proxy实现):
class PooledConnection implements Connection{ private final Connection conn; private final Pool pool; private bool closed = false; public PooledConnection(Connection conn, Pool pool){ this.pool = pool; this.conn = conn; } public delegate conn: Connection{ precondition(); delegate; postcondition(); } public void close(){ if(!closed){ pool.release(conn); closed = true; } } private void precondition(){ if(closed){ throw new ConnectionClosedException(); } } private void postcondition(){...} }
|
说明:
这里,delegate是一个keyword,它表示编译器自动加入委托代码。
一。
conn:Connection表示对conn对象做委托,而且只委托Connection接口里面的方法。(这可以用来做filtering)
二。
委托所带的是一个block。这个block是optional的。如果不带一个block,就是最简单的直接委托。
它内部可以带任意合法的block。特殊之处,是:
1。所有分支都必须或者throw 一个RuntimeException,或者return delegate()。
2。delegate()是一个特殊的函数,它代表调用被委托的函数,所有参数都被传递。
3。return 只能是return delegate()
4。delegate()可以不用return而直接调用。
5。delegate()的返回值未知。
三。
在类中直接定义的方法,可以override delegate的方法。
四。
如果一个类中定义了两个以上的delegate,那么任何两个delegate中的方法不能互相冲突。(即可以被认为一个方法的签名override了另一个)
从上面的示例代码可以看出,before, after等advice都可以加。
也可以用直接定义的close()来override委托函数。
下面,我在写一下对应observer pattern的代码
interface Observer{ void fireEvent(Event event); } interface Subject{ void addObserver(Observer ob); void removeObserver(Observer ob); void subjectChange(Event event); } class SubjectImpl implements Subject{ public void addObserver(Observer ob){...} public void removeObserver(Observer ob){...} public void subjectChange(Event event){ for all ob in observers ob.fireEvent(event); } } class LineSubject implements Subject, Line{ private final Subject sub; private final Line ln; public delegate sub:Subject; public delegate Line; public void setP1(Point p){ ln.setP1(p); sub.subjectChange(new LineChange(ln)); } public void setP2(Point p){ ln.setP2(p); sub.subjectChange(new LineChange(ln)); } public LineSubject(Subject sub, Line ln){ this.sub = sub; this.ln = ln; } }
|
这样,也可以达到重用observer代码的作用,而且,引入的额外东西比aspect要少,类型上和代码的简单程度也比dynamic proxy好。
各位觉得如何?