设计模式学习(四) 行为型 -2- 观察者 备忘录 访问者 状态 解释器
这一篇写剩下五个行为型设计模式:
观察者模式、备忘录模式、访问者模式、状态模式、解释器模式
#观察者模式(Observer Pattern) Define a one-to-many dependency between objects so that when one object changes state,all its dependents are notofied and updated automatically.
也称发布订阅模式。对象间存在一对多关系时、当一个对象改变状态、所有依赖他的对象会得到通知并自动更新。
优点:观察者和被观察者抽象耦合。观察者是一个集合、容易扩展。
缺点:如果观察者过多会花费很多时间 如观察者和观察者对象具有循环依赖会导致系统崩溃。观察者只知道发生了变化但不知道是如何变化的。
适用:一对多关系
四个角色:
抽象主题(Subject)角色:被观察者 可添加删除观察者
抽象观察者(Observer)角色:观察者接口
具体主题(Concrete Subject)角色:具体被观察者、需要发出通知
具体观察者(Concrete Observer)角色:实现抽象观察者接口
抽象主题:
public interface Subject { void addObserver(Observer observer); void removeObserver(Observer observer); void notifyObserver();// 通知 }
抽象观察者:
// 抽象观察者 public interface Observer { void print(); }
具体主题:
public class ISubject implements Subject { private List<Observer> list = new ArrayList<Observer>(); public void addObserver(Observer observer) { list.add(observer); } public void removeObserver(Observer observer) { list.remove(observer); } public void notifyObserver() { for (Observer o : list) { o.print(); } } // 业务方法 public void change() { this.notifyObserver(); } }
具体观察者:
public class IObserver implements Observer{ public void print() { System.out.println("IObserver1 收到通知!"); } }
测试:
#备忘录模式(Memento Pattern) Without violating encapsulation,capture and externalize an object's internal state sothat the object can be restored to this state later.
快照(Snapshot)模式或Token模式。在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。以便在适当的时侯恢复到原先保存的状态。比如取消。
优点:提供一个可恢复的机制 缺点:消耗资源
三个角色:
发起人(Originator)角色:定义哪些属于备份范围的状态
备忘录(Memento)角色:负责存储
负责人(Caretaker)角色:管理备忘录
发起人:
// 发起人 public class Originator { private String state; // 创建备忘录 public Memento createMemento(){ return new Memento(this.state); } public void restoreMemento(Memento memento){ this.setState(memento.getState()); } public String getState() { return state; } public void setState(String state) { this.state = state; } }
备忘录:
// 备忘录 public class Memento { private String state; public Memento(String state) { this.state = state; } public String getState() { return state; } public void setState(String state) { this.state = state; } }
负责人:
public class Caretaker { private Memento memento; public Memento getMemento() { return memento; } public void setMemento(Memento memento) { this.memento = memento; } }
测试:
#访问者模式(Visitor Pattern) Represent an operation to be performed on the elements of an object structure. Visitorlets you define a new operation without changing the classes of the elements on whichit operates.
使用一个访问者类,改变了元素类的执行算法。
优点:符合单一原则、优秀的可扩展性 新的操作仅需要增加新的访问者、关的行为集中到一个访问者对象中,而不是分散到一个个元素类中
缺点:违背了依赖倒置原则。违反了迪米特原则。新增元素困难。
五个角色:
抽象访问者(Visitor)角色:定义访问者可以访问哪些元素。 指定客户可以访问那些东西
具体访问者(Concrete Visitor)角色:各个访问操作 :客户
抽象元素(Element)角色:东西
具体元素(Concrete Element)角色:蔬菜 水果
结构对象(Object Structure)角色:可以遍历结构中的所有元素;如果需要,提供一个高层次的接口让访问者对象可以访问每一个元素
抽象访问者:客户接口
// 抽象访问者 public interface Visitor { // 可访问的对象 void visit(Fruit fruit); void visit(Vegetable vegetable); }
具体访问者:具体客户
1:
// 具体访问者 public class IVisitor implements Visitor{ public void visit(Fruit fruit) { System.out.println("水果:"+fruit.name); } public void visit(Vegetable vegetable) { System.out.println("蔬菜:"+vegetable.name); } }
2:
public class IVisitor2 implements Visitor { public void visit(Fruit fruit) { System.out.println(fruit.name+"多少钱?"); } public void visit(Vegetable vegetable) { System.out.println(vegetable.name+"怎么卖?"); } }
抽象元素:
public interface Element { void accept(Visitor visitor); }
具体元素:水果 蔬菜
public class Fruit implements Element { public String name; public Fruit(String name) { this.name = name; } public String getName() { return name; } public void accept(Visitor visitor) { visitor.visit(this); } }
public class Vegetable implements Element { public String name; public Vegetable(String name) { this.name = name; } public String getName() { return name; } public void accept(Visitor visitor) { visitor.visit(this); } }
结构对象:购物车
public class ShoppingCart { List<Element> list = new ArrayList<Element>(); public ShoppingCart() { list.add(new Fruit("苹果")); list.add(new Fruit("橙子")); list.add(new Vegetable("胡萝卜")); list.add(new Vegetable("白菜")); } public void print(Visitor visitor){ for(Element e:list){ e.accept(visitor); } } }
测试:
#状态模式(State Pattern) Allow an object to alter its behavior when its internal state changes. The object willappear to change its class.
允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类
三个角色:
抽象状态(State)角色:封装环境对象的一个特定状态所对应的行为
具体状态(Concrete State)角色:该角色实现环境的一个状态所对应的行为
环境(Context)角色:该角色定义客户端需要的接口,并负责具体状态的切换。它会保留一个具体状态类的实例,该实例给出环境对象的现有状态。
抽象状态:
public interface State { void onClick(Button btn); }
具体状态:
1:
public class StartState implements State { public void onClick(Button btn) { System.out.println("StartState"); btn.setState(this); } @Override public String toString() { return "StartState{}"; } }
2:
public class StopState implements State { public void onClick(Button btn) { System.out.println("StopState"); btn.setState(this); } @Override public String toString() { return "StopState{}"; } }
环境:
// 环境 public class Button { private State state; // get set public State getState() { return state; } public void setState(State state) { this.state = state; } }
测试:
#解释器模式(Interpreter Pattern) Given a language, define a representation for its grammar along with an interpreterthat uses the representation to interpret sentences in the language.
给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子。
五个角色:
抽象表达式(Abstract Expression)角色:
终结符表达式(Terminal Expression)角色:
非终结符表达式(Nonterminal Expression)角色:
环境(Context)角色:全局信息
客户端(Client)角色:调用
抽象表达式:
public interface Expression { boolean interpret(String context); }
public class IExpression implements Expression { private String data; public IExpression(String data) { this.data = data; } public boolean interpret(String context) { if(context.contains(data)){ return true; } return false; } @Override public String toString() { return "IExpression{" + "data='" + data + '\'' + '}'; } }
public class OrExpression implements Expression { private Expression e1 = null; private Expression e2 = null; public OrExpression(Expression e1, Expression e2) { this.e1 = e1; this.e2 = e2; } public boolean interpret(String context) { return e1.interpret(context) || e2.interpret(context); } }
public class AndExpression implements Expression { private Expression e1 = null; private Expression e2 = null; public AndExpression(Expression e1, Expression e2) { this.e1 = e1; this.e2 = e2; } public boolean interpret(String context) { return e1.interpret(context) && e2.interpret(context); } }
环境:
public class Context { //规则:Robert true John true public static Expression getMaleExpression(){ Expression robert = new IExpression("Robert"); Expression john = new IExpression("John"); return new OrExpression(robert, john); } //规则:Julie Married true public static Expression getMarriedWomanExpression(){ Expression julie = new IExpression("Julie"); Expression married = new IExpression("Married"); return new AndExpression(julie, married); } }
测试:
总结:
观察者模式 :对象间存在一对多关系时、当一个对象改变状态、所有依赖他的对象会得到通知并自动更新。
备忘录模式 :在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。以便在适当的时侯恢复到原先保存的状态。
访问者模式 :使用一个访问者类,改变了元素类的执行算法。
状态模式:允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类
解释器模式:给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子。
@