2013-04-11 41 views
0

例如这个观察者模式是否可以产生一个通用的方面?

https://github.com/eclipse/org.aspectj/blob/master/docs/sandbox/ubc-design-patterns/src/ca/ubc/cs/spl/aspectPatterns/patternLibrary/ObserverProtocol.java

可以写成像这样

public abstract aspect ObserverProtocol<S implements Subject, O implements Observer> { 
    // ... 
    protected abstract pointcut subjectChange(S s); 
    protected abstract void updateObserver(S subject, O observer); 
} 
+0

我知道这是一个旧的,但仍列出未答复。如果看起来合适,请您接受并提出我的答案吗?谢谢。 – kriegaex 2014-06-09 12:28:15

回答

1

是的,通用的抽象的方面是可能的,见AspectJ 5 Development Kit Developer's Notebook。你会在那里找到一个有启发性的例子。给我一个标志,如果你需要更多的帮助。


更新以低于你的问题的反应:嗯,在这种情况下,我没有看到在使用仿制药Observer模式太大的价值,但它是可能的,需要一些重构。我克隆了回购并重构了一些代码。现在,它读起来就像这样(对不起,这将是冗长的!):

package ca.ubc.cs.spl.aspectPatterns.patternLibrary; 

import java.util.WeakHashMap; 
import java.util.List; 
import java.util.LinkedList; 
import java.util.Iterator; 

public abstract aspect ObserverProtocol<S extends Subject, O extends Observer> { 
    private WeakHashMap<S, List<O>> perSubjectObservers = 
     new WeakHashMap<S, List<O>>(); 

    protected List<O> getObservers(S subject) { 
     List<O> observers = perSubjectObservers.get(subject); 
     if (observers == null) { 
      observers = new LinkedList<O>(); 
      perSubjectObservers.put(subject, observers); 
     } 
     return observers; 
    } 

    public void addObserver(S subject, O observer) { 
     getObservers(subject).add(observer); 
    } 

    public void removeObserver(S subject, O observer) { 
     getObservers(subject).remove(observer); 
    } 

    protected abstract pointcut subjectChange(S s); 

    after(S subject): subjectChange(subject) { 
     Iterator<O> iter = getObservers(subject).iterator(); 
     while (iter.hasNext()) 
      updateObserver(subject, iter.next()); 
    } 

    protected abstract void updateObserver(S subject, O observer); 
} 
package ca.ubc.cs.spl.aspectPatterns.patternLibrary; 

public interface Subject {} 
package ca.ubc.cs.spl.aspectPatterns.patternLibrary; 

public interface Observer {} 
package ca.ubc.cs.spl.aspectPatterns.examples.observer.aspectj; 

import java.awt.Color; 

public class Point { 
    private int x; 
    private int y; 
    private Color color; 

    public Point(int x, int y, Color color) { 
     this.x = x; 
     this.y = y; 
     this.color = color; 
    } 

    public int getX() { return x; } 
    public int getY() { return y; } 
    public void setX(int x) { this.x = x; } 
    public void setY(int y) { this.y = y; } 
    public Color getColor() { return color; } 
    public void setColor(Color color) { this.color = color; } 
} 
package ca.ubc.cs.spl.aspectPatterns.examples.observer.aspectj; 

public class Screen { 
    private String name; 

    public Screen(String s) { 
     this.name = s; 
    } 

    public void display(String s) { 
     System.out.println(name + ": " + s); 
    } 
} 
package ca.ubc.cs.spl.aspectPatterns.examples.observer.aspectj; 

import ca.ubc.cs.spl.aspectPatterns.patternLibrary.Subject; 
import ca.ubc.cs.spl.aspectPatterns.patternLibrary.Observer; 

public aspect SubjectObserverDeclarations { 
    declare parents: Point implements Subject; 
    declare parents: Screen implements Observer; 
    declare parents: Screen implements Subject; 
} 
package ca.ubc.cs.spl.aspectPatterns.examples.observer.aspectj; 

import java.awt.Color; 
import ca.ubc.cs.spl.aspectPatterns.patternLibrary.ObserverProtocol; 

public aspect ColorObserver extends ObserverProtocol<Point, Screen> { 
    declare precedence : SubjectObserverDeclarations, ColorObserver; 

    protected pointcut subjectChange(Point subject): 
     call(void Point.setColor(Color)) && target(subject); 

    protected void updateObserver(Point subject, Screen observer) { 
     observer.display("screen updated (point subject changed color)"); 
    } 
} 
package ca.ubc.cs.spl.aspectPatterns.examples.observer.aspectj; 

import ca.ubc.cs.spl.aspectPatterns.patternLibrary.ObserverProtocol; 

public aspect CoordinateObserver extends ObserverProtocol<Point, Screen>{ 
    declare precedence : SubjectObserverDeclarations, CoordinateObserver; 

    protected pointcut subjectChange(Point subject): 
     (call(void Point.setX(int)) || call(void Point.setY(int))) && target(subject); 

    protected void updateObserver(Point subject, Screen observer) { 
     observer.display("screen updated (point subject changed coordinates)"); 
    } 
} 
package ca.ubc.cs.spl.aspectPatterns.examples.observer.aspectj; 

import ca.ubc.cs.spl.aspectPatterns.patternLibrary.ObserverProtocol; 

public aspect ScreenObserver extends ObserverProtocol<Screen, Screen>{ 
    declare precedence : SubjectObserverDeclarations, ScreenObserver; 

    protected pointcut subjectChange(Screen subject): 
     call(void Screen.display(String)) && target(subject); 

    protected void updateObserver(Screen subject, Screen observer) { 
     observer.display("screen updated (screen subject displayed message)"); 
    } 
} 
package ca.ubc.cs.spl.aspectPatterns.examples.observer.aspectj; 

import java.awt.Color; 

public class Main { 
    public static void main(String argv[]) { 
     System.out.println("Creating screens s1, s2, s3, s4, s5 and point p"); 
     Point p = new Point(5, 5, Color.blue); 
     Screen s1 = new Screen("s1"); 
     Screen s2 = new Screen("s2"); 
     Screen s3 = new Screen("s3"); 
     Screen s4 = new Screen("s4"); 
     Screen s5 = new Screen("s5"); 

     System.out.println("Creating observing relationships:"); 
     System.out.println("- s1 and s2 observe color changes to p"); 
     System.out.println("- s3 and s4 observe coordinate changes to p"); 
     System.out.println("- s5 observes s2's and s4's display() method"); 

     ColorObserver.aspectOf().addObserver(p, s1); 
     ColorObserver.aspectOf().addObserver(p, s2); 

     CoordinateObserver.aspectOf().addObserver(p, s3); 
     CoordinateObserver.aspectOf().addObserver(p, s4); 

     ScreenObserver.aspectOf().addObserver(s2, s5); 
     ScreenObserver.aspectOf().addObserver(s4, s5); 

     System.out.println("Changing p's color:"); 
     p.setColor(Color.red); 

     System.out.println("Changing p's x-coordinate:"); 
     p.setX(4); 

     System.out.println("done."); 
    } 
} 

正如你所看到的,抽象的基本方面ObserverProtocol现在使用仿制药,但价格是我们现在需要方面SubjectObserverDeclarations我们declare parents声明,否则,因为如果我们声明的父母在他们里面派生方面不能使用类对派生方面来说,正确编译(鸡蛋和鸡蛋问题)就太迟了。

您也会看到,因此切入点subjectChange现在将其目标绑定到具体类,不再是接口Subject。同样,方法updateObserver也使用类而不是接口。

为了简单起见,我所提取的接口SubjectObserver从基本方面,以避免一个方面声明像:

public abstract aspect ObserverProtocol< 
    S extends ObserverProtocol.Subject, 
    O extends ObserverProtocol.Observer> 
{ 
    //... 
} 
+0

你能写一些代码示例吗?你将如何实现泛型的观察模式? – 2013-05-02 02:33:28

相关问题