有可能产生一般方面吗?

ut_sed 发布于 2019-03-09 aspectj 最后更新 2019-03-09 14:41 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);
}
已邀请:

aad

赞同来自:

是的,通用抽象方面是可能的,请参阅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>
{
    //...
}