Created
March 6, 2013 14:06
-
-
Save alessandroleite/5099508 to your computer and use it in GitHub Desktop.
Example of Observer Pattern with AspectJ
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package example.types; | |
import java.util.Arrays; | |
import example.pattern.Observer; | |
import example.pattern.Subject; | |
public class Husband extends Person implements Observer { | |
private Person wife; | |
public Husband(String name, Person wife) { | |
super(name); | |
this.wife = wife; | |
wife.attach(this); | |
} | |
@Override | |
public void update(Subject observable, Object... newState) { | |
System.out.print(observable + " has a new state: "); | |
Object[] states = (Object[]) newState[0]; | |
for (Object state : states) { | |
System.out.print(state + " "); | |
} | |
System.out.println(); | |
if (Arrays.binarySearch(states, "TPM") > -1 || Arrays.binarySearch(states, "Angry") > -1) { | |
System.out.println(this.getName() + " pay attention to your own safety!"); | |
} | |
} | |
public Person getWife() { | |
return wife; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package example.pattern; | |
public interface Observer { | |
void update(Subject observable, Object ... newState); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package example.aspects; | |
import java.util.Collection; | |
import java.util.Collections; | |
import java.util.concurrent.CopyOnWriteArrayList; | |
import example.pattern.Observer; | |
import example.pattern.Subject; | |
public abstract aspect ObserverPattern { | |
public abstract pointcut notifyObservers(Subject observable, Object newState); | |
/*after(Subject observable, Object newState) returning : notifyObservers(observable, newState) { | |
for (Observer obs : observable.getObservers()) { | |
obs.update(observable, newState); | |
} | |
}*/ | |
Object around(Subject observable, Object newState) : notifyObservers(observable, newState){ | |
Object advicedMethodReturn; | |
synchronized (thisJoinPoint.getTarget()) { | |
advicedMethodReturn = proceed(observable, newState); | |
} | |
for (Observer obs : observable.getObservers()) { | |
obs.update(observable, newState, advicedMethodReturn); | |
} | |
return advicedMethodReturn; | |
} | |
// Subject inter-type declaration | |
private final Collection<Observer> Subject.observers = new CopyOnWriteArrayList<Observer>(); | |
public void Subject.attach(Observer observer) { | |
if (observer != null && !observers.contains(observer)) { | |
observers.add(observer); | |
} | |
} | |
public void Subject.detach(Observer observer) { | |
if (observer != null) { | |
observers.remove(observer); | |
} | |
} | |
public Collection<Observer> Subject.getObservers() { | |
return Collections.unmodifiableCollection(this.observers); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package example.types; | |
public class Person { | |
private String name; | |
private Object[] emotions = new String[] { "happy" }; | |
public Person(String name) { | |
this.name = name; | |
} | |
public Object[] setEmotions(Object... args) { | |
Object[] before = this.emotions; | |
this.emotions = args; | |
return before; | |
} | |
public String getName() { | |
return name; | |
} | |
public Object[] getEmotions() { | |
return emotions; | |
} | |
@Override | |
public String toString() { | |
return this.getName(); | |
} | |
@Override | |
public int hashCode() { | |
final int prime = 31; | |
int result = 1; | |
result = prime * result + ((name == null) ? 0 : name.hashCode()); | |
return result; | |
} | |
@Override | |
public boolean equals(Object obj) { | |
if (this == obj) { | |
return true; | |
} | |
if (obj == null) { | |
return false; | |
} | |
if (getClass() != obj.getClass()) { | |
return false; | |
} | |
Person other = (Person) obj; | |
if (name == null) { | |
if (other.name != null) { | |
return false; | |
} | |
} else if (!name.equals(other.name)) { | |
return false; | |
} | |
return true; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package example.aspects; | |
import example.pattern.Subject; | |
import example.types.Person; | |
public aspect PersonAspect extends ObserverPattern { | |
declare parents: Person implements Subject; | |
public pointcut notifyObservers(Subject observable, Object newState): | |
target (observable) && (execution (* *.set*(..))) && args(newState); | |
// pointcut notifyObservers2(Subject observable, Object ... newState): | |
// target (observable) && (execution (* *.set*(..))) && args(newState); | |
// | |
// after(Subject observable, Object[] newState) returning: notifyObservers2(observable, newState) { | |
// for (Observer obs : observable.getObservers()) { | |
// obs.update(observable, newState); | |
// } | |
// } | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package example.pattern; | |
import java.util.Collection; | |
public interface Subject { | |
/** | |
* Add a new {@link Observer} to this observable ({@link Subject}) that will | |
* be notified when the state of the observable object change. | |
* | |
* @param obs | |
* The {@link Observable} to be add. Must be not | |
* <code>null</code>. | |
*/ | |
void attach(Observer obs); | |
/** | |
* Remove a given {@link Observer} of this {@link Subject}. | |
* | |
* @param obs | |
* The {@link Observer} to be removed of this {@link Subject}. | |
*/ | |
void detach(Observer obs); | |
/** | |
* Returns a read-only {@link Collection} with the {@link Observer}s of a | |
* {@link Subject}. | |
* | |
* @return A read-only {@link Collection} with the {@link Observer}s of a | |
* {@link Subject}. | |
*/ | |
Collection<Observer> getObservers(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment