たとえば、このオブザーバーパターン
そのように書くことができます
public abstract aspect ObserverProtocol<S implements Subject, O implements Observer> {
// ...
protected abstract pointcut subjectChange(S s);
protected abstract void updateObserver(S subject, O observer);
}
たとえば、このオブザーバーパターン
そのように書くことができます
public abstract aspect ObserverProtocol<S implements Subject, O implements Observer> {
// ...
protected abstract pointcut subjectChange(S s);
protected abstract void updateObserver(S subject, O observer);
}
はい、一般的な抽象的側面が可能です。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
ステートメントにアスペクトが必要になりました。そうしないと、派生アスペクトがクラスを使用できませんでした。正しくコンパイルするための派生アスペクト (鶏と卵の問題)。
その結果、pointcut がsubjectChange
そのターゲットを interface ではなく具象クラスにバインドするようになったこともわかりますSubject
。同様に、メソッドupdateObserver
もインターフェイスではなくクラスを使用します。
簡単にするために、次のようなアスペクト宣言を避けるために、基本アスペクトからインターフェイスSubject
を抽出しました。Observer
public abstract aspect ObserverProtocol<
S extends ObserverProtocol.Subject,
O extends ObserverProtocol.Observer>
{
//...
}