设计模式之组织行为(二)
高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。
画图不易,请勿转载。
对象行为组织类
Iterator(迭代器)
interface Iterator{
Object First();
Object Next();
boolean IsDone();
Object CurrentItem();
}
abstract class Aggregate{
abstract Iterator CreateIterator();
}
class ConcreteIterator implements Iterator{
private List<Object> list = new ArrayList<Object>();
private int curr=0;
public ConcreteIterator(List<Object> list){
this.list = list;
}
public Object First(){
return list.get(0);
}
public Object Next(){
Object ret = null;
curr++;
if(curr < list.size()){
ret = list.get(curr);
}
return ret;
}
public boolean IsDone(){
return curr>=list.size()?true:false;
}
public Object CurrentItem(){
return list.get(curr);
}
}
class ConcreteAggregate extends Aggregate{
private List<Object> list = new ArrayList<Object>();
public ConcreteAggregate(List<Object> list){
this.list = list;
}
public Iterator CreateIterator(){
return new ConcreteIterator(list);
}
}
class client{
public static void main(String[] args){
List<Object> list = new ArrayList<Object>();
list.add("miner");
list.add("any");
Aggregate agg = new ConcreteAggregate(list);
Iterator iterator = agg.CreateIterator();
iterator.First();
while(!iterator.IsDone()){
System.out.println(iterator.CurrentItem());
iterator.Next();
}
}
}
中介者(Mediator)
备忘录(Memento)
import java.util.List;
import java.util.ArrayList;
class Originator {
private String state;
// The class could also contain additional data that is not part of the
// state saved in the memento..
public void set(String state) {
this.state = state;
System.out.println("Originator: Setting state to " + state);
}
public Memento saveToMemento() {
System.out.println("Originator: Saving to Memento.");
return new Memento(this.state);
}
public void restoreFromMemento(Memento memento) {
this.state = memento.getSavedState();
System.out.println("Originator: State after restoring from Memento: " + state);
}
public static class Memento {
private final String state;
public Memento(String stateToSave) {
state = stateToSave;
}
// accessible by outer class only
private String getSavedState() {
return state;
}
}
}
class Caretaker {
public static void main(String[] args) {
List<Originator.Memento> savedStates = new ArrayList<Originator.Memento>();
Originator originator = new Originator();
originator.set("State1");
originator.set("State2");
savedStates.add(originator.saveToMemento());
originator.set("State3");
// We can request multiple mementos, and choose which one to roll back to.
savedStates.add(originator.saveToMemento());
originator.set("State4");
originator.restoreFromMemento(savedStates.get(1));
}
}
订阅/观察者模式(Observe)
class AbstractSubject(object):
def register(self, listener):
raise NotImplementedError("Must subclass me")
def deregister(self, listener):
raise NotImplementedError("Must subclass me")
def notify_listeners(self, event):
raise NotImplementedError("Must subclass me")
class Listener(object):
def __init__(self, name, subject):
self.name = name
subject.register(self)
def notify(self, event):
print self.name, "received event", event
class Subject(AbstractSubject):
def __init__(self):
self.listeners = []
self.data = None
def getUserAction(self):
self.data = raw_input('Enter something to do:')
return self.data
# Implement abstract Class AbstractSubject
def register(self, listener):
self.listeners.append(listener)
def deregister(self, listener):
self.listeners.remove(listener)
def notify_listeners(self, event):
for listener in self.listeners:
listener.notify(event)
if __name__=="__main__":
# make a subject object to spy on
subject = Subject()
# register two listeners to monitor it.
listenerA = Listener("<listener A>", subject)
listenerB = Listener("<listener B>", subject)
# simulated event
subject.notify_listeners ("<event 1>")
# outputs:
# <listener A> received event <event 1>
# <listener B> received event <event 1>
action = subject.getUserAction()
subject.notify_listeners(action)
#Enter something to do:hello
# outputs:
# <listener A> received event hello
# <listener B> received event hello
状态(state)
策略模式(Strategy)
模板方法(Template)
/**
* An abstract class that is common to several games in
* which players play against the others, but only one is
* playing at a given time.
*/
abstract class Game {
private int playersCount;
abstract void initializeGame();
abstract void makePlay(int player);
abstract boolean endOfGame();
abstract void printWinner();
/* A template method : */
final void playOneGame(int playersCount) {
this.playersCount = playersCount;
initializeGame();
int j = 0;
while (!endOfGame()){
makePlay(j);
j = (j + 1) % playersCount;
}
printWinner();
}
}
//Now we can extend this class in order to implement actual games:
class Monopoly extends Game {
/* Implementation of necessary concrete methods */
void initializeGame() {
// ...
}
void makePlay(int player) {
// ...
}
boolean endOfGame() {
// ...
}
void printWinner() {
// ...
}
/* Specific declarations for the Monopoly game. */
// ...
}
class Chess extends Game {
/* Implementation of necessary concrete methods */
void initializeGame() {
// ...
}
void makePlay(int player) {
// ...
}
boolean endOfGame() {
// ...
}
void printWinner() {
// ...
}
/* Specific declarations for the chess game. */
// ...
}
public class Player {
public static void main(String[] args) {
Game chessGame = new Chess();
chessGame.initializeGame();
chessGame.playOneGame(1); //call template method
}
}
访问者(visitor)
visistor模式在spring-beans中的应用:
/spring-beans/src/main/java/org/springframework/beans/factory/config/BeanDefinitionVisitor.java
/**
* Traverse the given BeanDefinition object and the MutablePropertyValues
* and ConstructorArgumentValues contained in them.
* @param beanDefinition the BeanDefinition object to traverse
* @see #resolveStringValue(String)
*/
public void visitBeanDefinition(BeanDefinition beanDefinition) {
visitParentName(beanDefinition);
visitBeanClassName(beanDefinition);
visitFactoryBeanName(beanDefinition);
visitFactoryMethodName(beanDefinition);
visitScope(beanDefinition);
visitPropertyValues(beanDefinition.getPropertyValues());
ConstructorArgumentValues cas = beanDefinition.getConstructorArgumentValues();
visitIndexedArgumentValues(cas.getIndexedArgumentValues());
visitGenericArgumentValues(cas.getGenericArgumentValues());
}