关注公众号获取更多资料
java
行为型模式描述的死程序运行时复杂的流程控制,描述了多个类或者对象之间怎样相互协调合做,涉及算法与对象之间的职责分配。git
行为型模式是23中设计模式中最为庞大的,包括如下11中:github
@算法
定义:模板方法定义一个操做中的算法骨架,将算法中的一些步骤延迟到子类中去,是的子类能够在不改变原有算法结构的状况下从新定义这些算法步骤。设计模式
模板方法模式主要包含一下几种结构:数据结构
抽象类:定义一个算法的轮廓和骨架多线程
具体子类:继承了抽象类并实现抽象方法。ide
根据以上角色结构能够大体画出以下类图:学习
举例说明:五一小长假出去旅游,须要选择地点,而后预约计划,最后选择出行方式,出行方式但是飞机,火车或者自驾游等。在这里选择地点,定计划,选择出行方式能够理解为模板方法,选择出行方式是抽象方法,判断出行方式为钩子方法,定计划步骤能够做为具体方法实现。测试
代码以下:
//抽象类 abstract class Travel { protected String destinate; //模板方法 protected Travel(String destinate) { System.out.println("去"+destinate+"..."); this.destinate = destinate; } public void travel() { plan(); if (travelHook()) { byTicket(); } else { byCar(); } } //具体方法 protected void plan() { System.out.println("预约计划..."); } //钩子方法 protected boolean travelHook() { return "beijing".equals(this.destinate); } //抽象方法 abstract void byTicket(); protected void byCar() { System.out.println("自驾游..."); } }
//具体子类 class Beijing extends Travel { public Beijing(String destinate) { super(destinate); } @Override void byTicket() { System.out.println("买飞机票..."); } } //具体子类 class Shanghai extends Travel{ public Shanghai(String destinate) { super(destinate); } @Override void byTicket() { } }
Travel beijing = new Beijing("beijing"); beijing.travel(); Travel shanghai = new Shanghai("shanghai"); shanghai.travel();
去beijing... 预约计划... 买飞机票... 去shanghai... 预约计划... 自驾游...
定义:定义了一系列算法,并将每一个算法封装起来,使之能够相互替代,而且算法的改变不会影响到使用者。
策略模式的结构以下:
根据以上结构能够画出以下类图:
模式的实现:
//抽象策略类 interface Strategy { void execute(); }
//具体策略类 class StrategyA implements Strategy { @Override public void execute() { System.out.println("do as strategyA..."); } } //具体策略类 class StrategyB implements Strategy { @Override public void execute() { System.out.println("do as strategyB..."); } }
//环境类 class Context { private Strategy strategy; public void setStrategy(Strategy strategy) { this.strategy = strategy; } public void executeMethod() { this.strategy.execute(); } }
Context context = new Context(); context.setStrategy(new StrategyA()); context.executeMethod();//do as strategyA... context.setStrategy(new StrategyB()); context.executeMethod();//do as strategyB...
对于一个庞大的系统来讲,一般状况下会有不少策略,此时若是直接使用原始的策略模式将会对策略的管理显得异常困难。将策略模式与工厂模式相结合而成的策略工厂模式将会使得对策略的管理更加方便。升级后的类图以下,代码比较简单,不作过多详解。
定义:将一个请求封装成一个对象,使发出的请求的责任和执行请求的责任分割开。
命令模式在平时生活中有不少场景,好比去餐厅吃饭,点餐时点的不一样的菜品至关于多个请求,随后这多个不一样的菜会到厨房分发给不一样的厨师,此时至关于执行请求的角色,在这个场景中就使得请求和执行分割,咱们点菜的人并不知道厨房具体是如何执行的。
命令模式结构:
类结构以下:
模式实现:
//抽象命令角色 interface ICommand { void execute(); }
//具体命令角色 class CommandA implements ICommand { private ReceiverA receiver; public CommandA() { receiver = new ReceiverA(); } @Override public void execute() { receiver.action(); } } //具体命令角色 class CommandB implements ICommand { private ReceiverB receiver; public CommandB() { receiver = new ReceiverB(); } @Override public void execute() { receiver.action(); } }
//请求者 class Invoker { private ICommand cmd; public Invoker(ICommand cmd) { this.cmd = cmd; } public void call() { cmd.execute(); } }
new Invoker(new CommandA()).call();//receiverA do... new Invoker(new CommandB()).call();//receiverB do...
一般状况下,一个请求须要多个接受者去完成,此时能够将命令模式和以前的组合模式相结合,组成宏命令模式又叫组合命令模式,具体类图以下,代码详见文章尾的GitHub地址。
定义:为避免请求发送者与多个请求处理者耦合在一块儿,将全部的请求处理者经过一个对象记住下一个对象的引用而造成一条链式结构;当有请求发生时,请求将沿着这条链传递,直到有对象处理它为止。
例如公司请假,请假三天以上和三天之内的审批人不一样,若是将全部的审批人都依赖于请求者,那么请求者中都须要依赖全部的审批人对象,若是将请假请求沿着审批人的链一个个传递下去,直到有人审批或者拒绝,请求中止,此时请求者对象只须要依赖一个审批人对象,从必定程度上下降了耦合。
模式结构:
类结构:
模式实现:
//抽象处理者 abstract class IHandler { private IHandler next; abstract void execute(String key); public void setNext(IHandler next) { this.next = next; } public IHandler getNext() { return this.next; } }
//具体处理者 class HandlerA extends IHandler { @Override void execute(String key) { if ("a".equals(key)) { System.out.println("handlerA do...."); return; } if (this.getNext() != null) { this.getNext().execute(key); return; } System.out.println("请求未处理..."); } } //具体处理者 class HandlerB extends IHandler { @Override void execute(String key) { if ("b".equals(key)) { System.out.println("handlerB do...."); return; } if (this.getNext() != null) { this.getNext().execute(key); return; } System.out.println("请求未处理..."); } }
IHandler handlerA = new HandlerA(); IHandler handlerB = new HandlerB(); handlerA.setNext(handlerB); handlerA.execute("a");//handlerA do.... handlerA.execute("b");//handlerB do.... handlerA.execute("c");//请求未处理...
定义:对有状态的对象,把复杂的判断逻辑提取到不一样的对象中,容许对象再起内部状态发生变化时改变其行为。
模式结构:
类结构:
举例说明:多线程在执行过程当中能够存在多个状态,能够简单的使用状态模式设计一个多线程的状态转换程序,代码以下:
//抽象状态 interface IThreadState { void execute(); }
//具体状态 class New implements IThreadState { @Override public void execute() { System.out.println("thread new..."); } } //具体状态 class Runnable implements IThreadState { @Override public void execute() { System.out.println("thread runnable..."); } } //具体状态 class Running implements IThreadState { @Override public void execute() { System.out.println("thread running..."); } } //具体状态 class Dead implements IThreadState { @Override public void execute() { System.out.println("thread dead..."); } }
//环境角色 class ThreadContext { private IThreadState state; public void start() { this.state = new New(); this.state.execute(); } public void runnable() { this.state = new Runnable(); this.state.execute(); } public void runnung() { this.state = new Running(); this.state.execute(); } public void stop() { this.state = new Dead(); this.state.execute(); } }
ThreadContext context = new ThreadContext(); context.start();//thread new... context.runnable();//thread runnable... context.runnung();//thread running... context.stop();//thread dead...
不少状况下,可能有多个环境享用一组状态,此时能够将状态模式和享元模式结合起来使用,在环境类中储存共享的状态。
定义:多个对象之间存在一对多的依赖关系,当一个对象的状态发生改变时,全部依赖于他的对象都会获得通知并自动更新。
模式结构:
注意:实现观察者模式时,具体目标和具体观察者之间不能直接调用,不然二者之间将紧密耦合在一块儿,违反了面对对象的设计原则。
类结构:
代码实现:
//抽象观察者 interface IObserver { void execute(); }
//具体观察者 class ObserverA implements IObserver { @Override public void execute() { System.out.println("observerA get..."); } } //具体观察者 class ObserverB implements IObserver { @Override public void execute() { System.out.println("observerB get..."); } }
//抽象主题 abstract class Subject { protected List<IObserver> observers = new ArrayList<>(); public void regiest(IObserver observer) { observers.add(observer); } public void remove(IObserver observer) { observers.remove(observer); } abstract void notifyObservers(); }
//具体主题 class ConcreteSubject extends Subject { @Override void notifyObservers() { for (IObserver observer : observers) { observer.execute(); } } }
Subject subject = new ConcreteSubject(); subject.regiest(new ObserverA()); subject.regiest(new ObserverB()); subject.notifyObservers(); //observerA get... //observerB get...
Java中经过java.util.Observable(抽象目标)和java.util.Observer(抽象观察者)定义了观察者模式,只要实现他们就能够编写观察者模式实例。
定义:定义一个中介对象来封装一系列对象之间的交互,使原有对象之间的耦合松散,而且能够独立的改变他们之间的交互。
模式结构:
类结构:
代码实现:
//抽象中介者 interface Mediator { void register(Colleague colleague); void relay(Colleague colleague); }
//抽象同事类 abstract class Colleague { protected Mediator mediator; public void setMediator(Mediator mediator) { this.mediator = mediator; } abstract void receive(); abstract void send(); }
//具体同事类 class ColleagueA extends Colleague { @Override void receive() { System.out.println("colleagueA received..."); } @Override void send() { System.out.println("colleagueA send..."); mediator.relay(this);//请求中介者转发 } } //具体同事类 class ColleagueB extends Colleague { @Override void receive() { System.out.println("colleagueB received..."); } @Override void send() { System.out.println("colleagueB send..."); mediator.relay(this);//请求中介者转发 } }
//具体中介者 class ConcreteMediator implements Mediator { private List<Colleague> colleagus = new ArrayList<>(); @Override public void register(Colleague colleague) { colleagus.add(colleague); colleague.setMediator(this); } @Override public void relay(Colleague colleague) { for (Colleague co : colleagus) { if (!co.equals(colleague)) { co.receive(); } } } }
Mediator mediator = new ConcreteMediator(); Colleague a = new ColleagueA(); Colleague b = new ColleagueB(); mediator.register(a); mediator.register(b); a.send(); b.send(); //colleagueA send... //colleagueB received... //colleagueB send... //colleagueA received...
观察者模式和中介者模式功能很相似,都是一个对象改变状态通知其余对象。不一样的是,观察者拥有全部被观察对象的全部引用,经过接口类型依赖,而中介者模式,变化的对象不能直接与被通知的对象直接联系,他不知道到底有多少对象被通知了,而是经过第三方进行操做。
具体内容能够参考:http://www.sohu.com/a/207062452_464084
定义:提供一个对象来顺序访问聚合对象中的一系列数据,二部暴露聚合对象的内部表示。
模式结构:
类结构:
代码实现:
//抽象聚合角色 abstract class Aggregate<T> { protected List<T> list; public void add(T t) { list.add(t); } abstract Iterator getIterator(); }
//抽象迭代器 interface Iterator<T> { boolean hasNext(); T next(); }
//具体聚合角色 class ConcreteAggregate extends Aggregate { public ConcreteAggregate() { list = new ArrayList(); } @Override Iterator getIterator() { return new ConcreteIterator(list); } }
//具体迭代器 class ConcreteIterator<T> implements Iterator { private List<T> list; private int index = 0; public ConcreteIterator(List<T> list) { this.list = list; } @Override public boolean hasNext() { return list.size() > index; } @Override public T next() { return list.get(index++); } }
Aggregate aggregate = new ConcreteAggregate(); aggregate.add("a"); aggregate.add("b"); aggregate.add("c"); aggregate.add("d"); Iterator iterator = aggregate.getIterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); } //a //b //c //d
一般状况下,迭代器模式还能够与组合模式相结合使用,使用迭代器遍历相似树结构的数据,类图以下,代码不作过多展现。
定义:将做用于某种数据结构种的各元素的操做分离出来封装成独立的类,使其在不改变数据结构的前提下能够添加做用于这些元素的新操做,为数据结构种的每一个元素提供多种访问方式。
模式结构:
类结构:
代码实现:
//抽象元素 interface Element { void sayHello(); }
//具体元素 class ElementA implements Element { @Override public void sayHello() { System.out.println("hi,i am elementA..."); } } class ElementB implements Element { @Override public void sayHello() { System.out.println("hi,i am elementB..."); } }
//抽象访问者 interface Visitor { void visit(Element el); }
//具体访问者 class VisitorA implements Visitor { @Override public void visit(Element el) { System.out.print("visitorA Knock knock..."); el.sayHello(); } } class VisitorB implements Visitor { @Override public void visit(Element el) { System.out.print("visitorB Knock knock..."); el.sayHello(); } }
//结构类 class Structure { private List<Element> elements = new ArrayList<>(); public void add(Element el) { this.elements.add(el); } public void accept(Visitor visitor) { elements.forEach(el -> visitor.visit(el)); } }
Structure structure = new Structure(); structure.add(new ElementA()); structure.add(new ElementB()); structure.accept(new VisitorA()); System.out.println("-------------"); structure.accept(new VisitorB());
visitorA Knock knock...hi,i am elementA... visitorA Knock knock...hi,i am elementB... ------------- visitorB Knock knock...hi,i am elementA... visitorB Knock knock...hi,i am elementB...
一般状况下,对象结构种有多个具体元素,此时还能够将访问者模式和组合模式相结合,在遍历这多个具体元素的时候还可使用上面的迭代器模式,非常灵活。
定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象以外保存这个对象,以便之后须要时能将这个对象恢复到以前的状态。
模式结构:
类结构:
代码实现:
//备忘录 class Memento { private Stack<String> states = new Stack<>(); public void pushState(String state) { states.push(state); } public String popState() { return states.peek() != null ? states.pop() : ""; } }
//管理者 class Caretaker { private Memento memento; public void setMemento(Memento m) { this.memento = m; } public Memento getMemento() { return this.memento; } }
//发起人 class Originator { private String state; public void setState(String state) { this.state = state; } public String getState() { return this.state; } public Memento createMemento() { Memento m = new Memento(); m.pushState(this.state); return m; } public void restoreState(Memento m) { this.state = m.popState(); } }
Originator originator = new Originator(); Caretaker caretaker = new Caretaker(); caretaker.setMemento(originator.createMemento()); System.out.println("------set------"); originator.setState("1"); System.out.println(originator.getState()); caretaker.getMemento().pushState("1"); originator.setState("2"); System.out.println(originator.getState()); caretaker.getMemento().pushState("2"); originator.setState("3"); System.out.println(originator.getState()); caretaker.getMemento().pushState("3"); System.out.println("------restore------"); originator.restoreState(caretaker.getMemento()); System.out.println(originator.getState()); originator.restoreState(caretaker.getMemento()); System.out.println(originator.getState()); originator.restoreState(caretaker.getMemento()); System.out.println(originator.getState());
------set------ 1 2 3 ------restore------ 3 2 1
定义:给分析对象一个语言,并定义该语言的文法表示,再设计一个解释器来解析语言中的句子。
刚开始看到解释器模式的定义的时候,一脸懵逼。编译器模式经常使用于对简单语言的编译或分析。在介绍编译器模式以前,首先介绍一下文法,句子,语法树等概念。
- 文法:描述语言语法结构的形式规则。好比<句子> ::=<主语><谓语><宾语>,<名词> ::= 大学生|课程|语文。“::=”表示定义为。用“<”,“>”包含的是非终结符,没有括住的是终结符(这两个概念后面要用)。
- 句子:语言的基本单位。
- 语法树:句子结构的一种树形表示。
介绍完上面的几个概念,看一下解释器模式的几个主要角色:
举例说明:公交车刷卡的时候只有广州和深圳的老年人和小学生是免费的,其余的都是2元车票钱,刷卡机须要根据输入的信息断定是否须要扣钱,那么文法能够定义为:<结果> ::= <城市>的<角色>。根据上面的模式角色,具体的模式类图以下:
具体代码设计以下:
//抽象表达式 interface Expression { boolean interpret(String info); }
//终结符表达式 class TerminalExpression implements Expression { private Set<String> set; public TerminalExpression(String[] data) { this.set = new HashSet<>(Arrays.asList(data)); } @Override public boolean interpret(String info) { return set.contains(info); } }
//非终结符表达式 class AndExpression implements Expression { private Expression city; private Expression person; public AndExpression(Expression city, Expression person) { this.city = city; this.person = person; } @Override public boolean interpret(String info) { String[] infos = info.split("的"); return city.interpret(infos[0]) && person.interpret(infos[1]); } }
//环境 public static void main(String[] args) { Expression city = new TerminalExpression(new String[]{"深圳", "广州"}); Expression person = new TerminalExpression(new String[]{"老年人", "小学生"}); Expression bus = new AndExpression(city, person); //排队上车 for (String p : new String[]{"深圳的老人", "广州的小学生", "深圳的年轻人", "广州的妇女", "深圳的小学生"}) { if (bus.interpret(p)) { System.out.println(p + "乘车免费..."); continue; } System.out.println(p + "刷卡2元..."); } }
深圳的老人刷卡2元... 广州的小学生乘车免费... 深圳的年轻人刷卡2元... 广州的妇女刷卡2元... 深圳的小学生乘车免费...
END
至此,通过三周的时间,23种设计模式的概念和大体使用方法都已经大致的学习完成,但这并不意味着结束。在实际应用中,咱们不只仅停留在概念以及一些简单的例子上,还须要知道每种模式具体在业务中如何使用,以及如何选择使用何种模式。了解熟悉每种设计模式的优缺点,除此以外,还须要熟悉设计模式中设计的一些法则和算法。加油,共勉!!
学海无涯,苦海做舟。争取早日掉光头发,由于光头……强。
本系列参考人民邮电出版社《软件设计模式(Java版)》