行为型模式
行为型模式关注的是各个类之间的相互作用,将职责划分清楚,使得我们的代码更加的清晰。
1.观察者模式
观察者模式,又叫发布-订阅模式。观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
Subject类:他把所有对观察者对象的引用保存在一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。
Observer类:抽象观察者,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。
ConcreteSubject类:具体主题类,将有关状态存入具体观察者对象,在具体主题的内部状态改变时,给所有登记过的观察者发出通知。
ConcreteObserver类:具体观察者,实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。
public class Subject {
private List<Observer> observers = new ArrayList<Observer>();
public void attach(Observer observer) {
observers.add(observer);
}
public void detach(Observer observer) {
observers.remove(observer);
}
public void notice() {
for(Observer o:observers) {
o.update();
}
}
}
-------
public class ConcreteSubject extends Subject{
private String subjectState;//具体主题状态
public String getSubjectState() {
return subjectState;
}
public void setSubjectState(String subjectState) {
this.subjectState = subjectState;
}
}
-----------
public abstract class Observer {
public abstract void update();
}
-----------
public class ConcreteObserver extends Observer{
private String name;
private String observerState;
private ConcreteSubject subject;
public ConcreteObserver(String name, ConcreteSubject subject) {
super();
this.name = name;
this.subject = subject;
}
@Override
public void update() {
observerState = subject.getSubjectState();
System.out.println("观察者的新状态是:"+name+":"+observerState);
}
public ConcreteSubject getSubject() {
return subject;
}
public void setSubject(ConcreteSubject subject) {
this.subject = subject;
}
}
------
public class Test {
public static void main(String[] args) {
ConcreteSubject s = new ConcreteSubject();
s.attach(new ConcreteObserver("x",s));
s.attach(new ConcreteObserver("y",s));
s.attach(new ConcreteObserver("z",s));
s.setSubjectState("来了");
s.notice();
}
}
什么时候用观察者模式?
当一个对象的改变需要同时改变其他对象的时候,而且不知道具体有多少对象有待改变时,应该考虑用观察者模式。
观察者模式的不足:
抽象主题还是依赖抽象观察者。
每一个观察者,可能被通知时发生的动作不一样。
解决方法:事件委托实现
去掉了父类观察者
2.模板方法
模板方法模式,定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
角色:
AbstractClass:实现了一个模板方法,定义了算法的骨架,具体子类将重定义PrimitiveOperation以实现一个算法的步骤。
ConcreteClass:实现PrimitiveOperation以完成算法中与特定子类相关的步骤。
public abstract class AbstractClass {
public abstract void operation1();
public abstract void operation2();
public void tempateMethod() {
operation1();
operation2();
System.out.println("模板方法");
}
}
------------
public class ConcreteClassA extends AbstractClass{
@Override
public void operation1() {
System.out.println("类A方法1");
}
@Override
public void operation2() {
System.out.println("类A方法2");
}
}
----
public class ConcreteClassB extends AbstractClass{
@Override
public void operation1() {
System.out.println("类B方法1");
}
@Override
public void operation2() {
System.out.println("类B方法2");
}
}
-----
public class Test {
public static void main(String[] args) {
AbstractClass c;
c= new ConcreteClassA();
c.tempateMethod();
c= new ConcreteClassB();
c.tempateMethod();
}
}
模板方法的优势:
模板方法模式是通过把不变行为搬移到超类,去除子类中重复代码来体现他的优势。
3.命令模式
命令模式,将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
角色:
invoker:要求该命令执行这个请求
Command:用来声明执行操作的接口
ConcreteCommand:将一个接受者对象绑定于一个动作,调用接受者相应的操作,以实现Execute.
Receiver:知道如何实施与执行一个请求相关的操作,任何类都可能作为一个接收者。
public abstract class Command {
protected Receiver receiver;
public Command(Receiver receiver) {
this.receiver = receiver;
}
public abstract void execute();
}
-----
public class Receiver {
public void Action() {
System.out.println("执行请求!");
}
}
----
public class ConcreteCommand extends Command{
public ConcreteCommand(Receiver receiver) {
super(receiver);
}
@Override
public void execute() {
receiver.Action();
}
}
-----
public class Invoker {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void executeCommand() {
command.execute();
}
}
-----
public class Test {
public static void main(String[] args) {
Receiver r = new Receiver();
Command c = new ConcreteCommand(r);
Invoker i = new Invoker();
i.setCommand(c);
i.executeCommand();
}
}
命令模式的作用
1.它能较容易地设计一个命令队列
2.在需要的时候,可以容易的将命令记入日志。
3.允许接收请求的一方决定是否要否决请求。
4.可以容易的实现对请求的撤掉与重做。
5.由于加进新的具体命令类不影响其他的类,因此增加新的具体命令类很容易。
4.职责链模式
职责链模式,使多个对象都有机会处理请求,从而避免请求的发送者与接收者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理完为止。
角色:
Handler:定义一个处理请示的接口
ConcreteHandler1:具体处理者类,处理它所负责的请求,可访问它的后继者,如果可处理该请求,就处理之,否则,就将该请求转发给它的后继者。
public abstract class Handler {
protected Handler successor;
//设置继任者
public void SetSuccessor(Handler successor) {
this.successor = successor;
}
public abstract void HandleRequest(int request);
}
----
public class ConcreteHandler1 extends Handler{
@Override
public void HandleRequest(int request) {
if(request>=0&&request<10) {
System.out.println("处理请求");
}else {
if(successor!=null)
successor.HandleRequest(request);
}
}
}
-----
public class ConcreteHandler2 extends Handler{
@Override
public void HandleRequest(int request) {
if(request>=10&&request<20) {
System.out.println("处理请求");
}else {
if(successor!=null)
successor.HandleRequest(request);
}
}
}
----
public class ConcreteHandler3 extends Handler{
@Override
public void HandleRequest(int request) {
if(request>=20) {
System.out.println("处理请求");
}else {
if(successor!=null)
successor.HandleRequest(request);
}
}
}
----
public class Test {
public static void main(String[] args) {
Handler h1 = new ConcreteHandler1();
Handler h2 = new ConcreteHandler2();
Handler h3 = new ConcreteHandler3();
h1.SetSuccessor(h2);
h2.SetSuccessor(h3);
h1.HandleRequest(5);
}
}
职责链的好处:
当客户提交一个请求时,请求时沿链传递直至有一个ConcreteHandler对象负责处理它。
5.状态模式
状态模式,当一个对象的内在状态改变时,允许改变其行为,这个对象看起来像是改变了其类。
状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中。可以把复杂的判断逻辑简化。
角色:
State:抽象状态类,定义一个接口以封装与Context的的一个特定状态相关的行为。
ConcreteStateA:具体状态,每一个子类实现一个与Context的一个状态相关的行为。
Context:维护一个ConcreteState子类的实例,这个实例定义当前的状态
public abstract class State {
public abstract void Handle(Context context);
}
-----
//维护一个ConcreteState类的实例,这个实例定义当前的状态
public class Context {
private State state;
public Context(State state) {
this.state = state;
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
public void Request() {
state.Handle(this);
}
}
------
public class ConcreteStateA extends State{
@Override
public void Handle(Context context) {
context.setState(new ConcreteStateB());
}
}
----
public class ConcreteStateB extends State {
@Override
public void Handle(Context context) {
context.setState(new ConcreteStateA());
}
}
------
public class Test {
public static void main(String[] args) {
Context c = new Context(new ConcreteStateA());
c.Request();
c.Request();
c.Request();
}
}
状态模式的好处与用处:
状态模式的好处是将与特定状态相关的行为局部化,并且将不同的状态的行为分割开来。
状态模式通过把各种状态转移逻辑分布到State的子类之间,来减少相互间的依赖。
当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式了。
6.解释器模式
解释器模式,给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
角色:
Context:包含解释器之外的一些全局信息。
AbstractExpresion:抽象表达式,声明一个抽象的解释操作,这个接口为抽象语法树中所有节点所共享。
TerminalExpression:终结符表达式,实现与文法中的终结符相关联的解释操作。
NonterminalExpression:非终结符表达式,为文法中的非终结符实现解释操作。对文法中的每一条规则R1,R2…Rn都需要一个具体的非终结符表达式类。
通常当有一个语言需要解释执行,并且你可将该语言中的句子表示为一个抽象语法树时,可使用解释器模式。
用了解释器模式,就意味着可以很容易的改变和扩展语法,因为该模式使用类来表示文法规则,你可使用继承来改变或扩展该文法。也比较容易实现文法,因为定义抽象语法树中各个节点的类的实现大体类似,这些类都易于直接编写。
7.中介者模式
中介者模式,用一个中介对象来封装一系列的对象交互。中介者使对象不需要显示地相互引用,从而使其耦合松散,而且可以独立地改变他们之间的交互。
角色:
Mediator:抽象中介者,定义了同事对象到中介者对象的接口
ConcreteMediator:具体中介者对象,实现抽象类的方法,它需要知道所有具体同事类,并从具体同事接受消息,向具体同事对象发出命令。
Colleague:抽象同事类
ConcreteColleague:具体同事类
public abstract class Mediator {
public abstract void send(String message,Colleague colleague);
}
-------
public abstract class Colleague {
protected Mediator mediator;
public Colleague(Mediator mediator) {
this.mediator = mediator;
}
}
--------
public class ConcreteMediator extends Mediator{
private ConcreteColleague1 colleague1;
private ConcreteColleague2 colleague2;
public ConcreteColleague1 getColleague1() {
return colleague1;
}
public void setColleague1(ConcreteColleague1 colleague1) {
this.colleague1 = colleague1;
}
public ConcreteColleague2 getColleague2() {
return colleague2;
}
public void setColleague2(ConcreteColleague2 colleague2) {
this.colleague2 = colleague2;
}
@Override
public void send(String message, Colleague colleague) {
if(colleague == colleague1) {
colleague2.notice(message);
}else {
colleague1.notice(message);
}
}
}
--------
public class ConcreteColleague1 extends Colleague{
public ConcreteColleague1(Mediator mediator) {
super(mediator);
}
public void send(String message) {
mediator.send(message, this);
}
public void notice(String message) {
System.out.println("1");
}
}
------
public class ConcreteColleague2 extends Colleague{
public ConcreteColleague2(Mediator mediator) {
super(mediator);
}
public void send(String message) {
mediator.send(message, this);
}
public void notice(String message) {
System.out.println(2);
}
}
-------
public class Test {
public static void main(String[] args) {
ConcreteMediator mediator = new ConcreteMediator();
ConcreteColleague1 colleague1 = new ConcreteColleague1(mediator);
ConcreteColleague2 colleague2 = new ConcreteColleague2(mediator);
mediator.setColleague1(colleague1);
mediator.setColleague2(colleague2);
colleague1.send("我是1号");
colleague2.send("我是2号");
}
}
中介者模式优缺点:
1.Mediator的出现减少了各个Colleague的耦合,使得可以独立地改变和复用各个Colleague和Mediator。
2.由于把对象如何协作进行了抽象,将中介作为一个独立的概念并封装在一个对象中,这样关注的对象就从对象各自本身的行为转移到它们之间的交互上来,也就是站在一个更宏观的角度去看待系统。
由于ConcreteMediator控制了集中化,于是就把交互复杂性变为了中介者的复杂性,这就使得中介者变得比任何一个ConcreteColleague都复杂。
8.访问者模式
访问者模式,表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
角色:
Visitor:为该对象结构中ConcreteElement的每一个类声明一个visit操作
ConcreteVisitor:具体访问者,实现每个由Visitor声明的操作。每个操作实现算法的一部分,而该算法片段乃是对应于结构中对象的类。
ObjectStructure:能枚举它的元素,可以提供一个高层的接口以允许访问者访问它的元素。
Element:定义一个Accept操作,他以一个访问者为参数
ConcreteElement:具体元素,实现Accept操作
访问者模式适用于数据结构相对稳定的系统。
访问者模式的目的是要把处理从数据结构分离出来。很多系统可以按照算法和数据结构分开,如果这样的系统有比较稳定的数据结构,又有易于变化的算法的话,使用访问者模式就是比较合适的,因为访问者模式使得算法操作的增加变得容易。
public abstract class Visitor {
public abstract void visitConcreteElementA(ConcreteElementA concreteElementA);
public abstract void visitConcreteElementB(ConcreteElementB concreteElementB);
}
-----
public class ConcreteElementA extends Element{
@Override
public void Accept(Visitor visitor) {
visitor.visitConcreteElementA(this);
}
public void operationA() {
}
}
----
public class ConcreteElementB extends Element{
@Override
public void Accept(Visitor visitor) {
visitor.visitConcreteElementB(this);
}
public void operationB() {
}
}
---
public class ConcreteVisitor1 extends Visitor{
@Override
public void visitConcreteElementA(ConcreteElementA concreteElementA) {
System.out.println();
}
@Override
public void visitConcreteElementB(ConcreteElementB concreteElementB) {
System.out.println();
}
}
---
public class ConcreteVisitor2 extends Visitor{
@Override
public void visitConcreteElementA(ConcreteElementA concreteElementA) {
}
@Override
public void visitConcreteElementB(ConcreteElementB concreteElementB) {
}
}
-----
public abstract class Element {
public abstract void Accept(Visitor visitor);
}
----
import java.util.ArrayList;
import java.util.List;
public class ObjectStructure {
private List<Element> elements = new ArrayList();
public void attach(Element element) {
elements.add(element);
}
public void remove(Element element) {
elements.remove(element);
}
public void accept(Visitor visitor) {
for(Element e:elements) {
e.Accept(visitor);
}
}
}
----
public class Test {
public static void main(String[] args) {
ObjectStructure o = new ObjectStructure();
o.attach(new ConcreteElementA());
o.attach(new ConcreteElementB());
ConcreteVisitor1 v1 = new ConcreteVisitor1();
ConcreteVisitor2 v2 = new ConcreteVisitor2();
o.accept(v1);
o.accept(v2);
}
}
9.策略模式
策略模式,定义了算法家族,分别封装起来,让她们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。
角色:
Strategy:策略类,定义所有支持的算法的公共接口
ConcreteStrategyA:具体策略类,封装了具体的算法或行为,继承于Strategy
Context上下文:用一个ConcreteStrategy来配置,维护一个对Strategy对象的引用。
public abstract class Strategy {
public abstract void algorithmInterface();
}
---
public class ConcreteStrategyA extends Strategy{
@Override
public void algorithmInterface() {
System.out.println("算法A的实现");
}
}
----
public class ConcreteStrategyB extends Strategy{
@Override
public void algorithmInterface() {
System.out.println("算法B的实现");
}
}
----
public class Context {
Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public void ContextInterface() {
strategy.algorithmInterface();
}
}
---
public class Test {
public static void main(String[] args) {
Context context;
//实例化不同的策略,最终调用context.contextInterface()所得的结果也不同
context = new Context(new ConcreteStrategyA());
context.ContextInterface();
context = new Context(new ConcreteStrategyB());
context.ContextInterface();
}
}
策略模式是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。
策略模式的Strategy类层次为context定义了一系列的可重用的算法或行为。继承有助于析取出这些算法中的公共功能。
策略模式的优点是简化了单元测试,因为每个算法都有自己的类,可以通过自己的接口单独测试。
10.备忘录模式
备忘录:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
角色:
Originator:负责创建一个备忘录Memento,用以记录当前时刻它的内部状态,并可使用备忘录恢复内部状态。
Memento:负责存储Originator对象的内部状态,并可防止Originator以外的其他对象访问备忘录Memento。
Caretakeer:负责保存好备忘录Memento
public class Originator {
private String state;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public Memento CreateMemento() {
return (new Memento(state));
}
public void setMemento(Memento memento) {
state = memento.getState();
}
public void show() {
System.out.println(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;
}
}
-------
public class Test {
public static void main(String[] args) {
Originator o = new Originator();
o.setState("0n");
o.show();
Caretaker c = new Caretaker();
c.setMemento(o.CreateMemento());
o.setState("off");
o.show();
o.setMemento(c.getMemento());
o.show();
}
}
--------
Memento模式比较适用于功能比较复杂的,但需要维护或记录属性历史的类,或者需要保存的属性只是众多属性中的一小部分,Originator可以根据保存的Memento信息还原到前一状态。
11.迭代器模式
迭代器模式,提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。
当你需要访问一个聚集对象,而不用管这些对象是什么都需要遍历的时候,你就应该考虑用迭代器模式。
角色:
Iterator:迭代抽象类,用户定义得到开始对象,得到下一个对象,判断是否到结尾,当前对象等抽象方法,统一接口。
ConcreteIterator:具体迭代器类,继承Iterator,实现开始,下一个,是否结尾,当前对象等方法。
Aggregate:聚集抽象类
ConcreteAggregate:具体聚集类。
例如 java集合中的迭代器