呵呵,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好。
各位觉得如何?