行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作完成单个对象无法完成的任务。行为型模式包括11种,因篇幅限制,切分为两篇进行总结介绍,本篇介绍前5种行为型设计模式:模板方法模式、策略模式、命令模式、职责链模式与状态模式。
模板方法模式是指定义一个操作中的算法骨架,将算法的一些步骤延迟到子类当中,使得子类可以不改变该算法结构的情况下重新定义该算法的某些特定步骤。现实情境中的论文模板、简历模板等都是模板方法模式。
模板方法模式的关键在于定义一个算法流程的骨架,提取出节点方法,封装在抽象类中。其中不变的方法在抽象类中编写方法实体,可变的方法则定义为抽象方法在具体子类中实体化,客户端只需实例化具体子类即可调用特定模板流程。
模板方法模式包含以下角色:抽象模板、具体实现。
public class TemplTest { public static void main(String[] args) { AbstractClass template = new ConcreteClass(); template.TemplateMethod(); } } //抽象类 abstract class AbstractClass { //模板方法 public void TemplateMethod() { SpecificMethod(); abstractMethod1(); abstractMethod2(); } //具体方法 public void SpecificMethod() { System.out.println("抽象类中的具体方法被调用"); } //抽象方法1 public abstract void abstractMethod1(); //抽象方法2 public abstract void abstractMethod2(); } //具体子类 class ConcreteClass extends AbstractClass { public void abstractMethod1() { System.out.println("抽象方法1的实现被调用"); } public void abstractMethod2() { System.out.println("抽象方法2的实现被调用"); } }
程序运行结果输出如下:
抽象类中的具体方法被调用 抽象方法1的实现被调用 抽象方法2的实现被调用
策略模式定义一系列的算法,并将每个算法进行封装,使得算法之间可以相互替换,且算法的变化不会影响到使用算法的客户,将使用算法的责任和算法的实现分割开来。现实情境中的坐飞机还是坐火车出行、刷卡还是现金支付等都是策略模式。
策略模式包含以下角色:抽象策略类、具体策略类、环境类。
策略模式的关键在于将算法的实现与算法的调用进行拆分,通过Context中间类的设置,在Context中封装了策略对象,使得客户端避免直接调用具体策略类方法,而是通过Context进行动态传入策略类对象,由Context类进行统一的策略方法调用。
public class StrategyTest { public static void main(String[] args) { Context c = new Context(); Strategy s = new ConcreteStrategyA(); c.setStrategy(s); c.strategyMethod(); System.out.println("-----------------"); s = new ConcreteStrategyB(); c.setStrategy(s); c.strategyMethod(); } } //抽象策略类 interface Strategy { public void strategyMethod();//策略方法 } //具体策略A class ConcreteStrategyA implements Strategy { public void strategyMethod() { System.out.println("具体策略A的策略被访问"); } } //具体策略A class ConcreteStrategyB implements Strategy { public void strategyMethod() { System.out.println("具体策略B的策略被访问"); } } //环境类 class Context { private Strategy strategy; public Strategy getStrategy() { return strategy; } public void setStrategy(Strategy strategy) { this.strategy = strategy; } public void strategyMethod() { strategy.strategyMethod(); } }
程序运行结果输出如下:
具体策略A的策略被访问 ----------------- 具体策略B的策略被访问
命令模式是指将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开,两者之间通过命令对象进行沟通。现实情境中的电视机遥控器(命令发送者)通过按钮(具体命令)来遥控电视机(命令接收者)就是命令模式。
命令模式包含以下角色:抽象命令类、具体命令类、接收者、请求者。
命令模式的关键在于将命令调用的请求者、命令对象、命令执行对象进行分割,实现命令调用请求者与实现者的解耦。调用者在调用时实例化具体的命令对象,而具体命令对象中又封装了特定的命令接收对象,执行特定的命令操作。
命令模式与策略模式的类图的确很相似,只不过命令模式多了一个接收者的角色。但是,虽然结构相似,但两者之间的区别还是很明显的。
策略模式的意图是封装算法,它认为算法是一个完整的、不可拆分的原子业务(注意不是原子对象),即让这些算法独立,并且可以相互替换,让行为的变化独立于拥有行为的客户;而命令模式则是针对于动作的解耦,把一个动作的执行分为执行对象(接收者)和执行行为(命令类),让两者相互独立而互不影响。
策略模式中的抽象算法和具体算法与命令模式的接收者非常相似,但是它们的职责不同。策略模式中的具体算法是负责一个完整算法逻辑,它是不可再拆分的原子业务单元,一旦变更就是对算法整体的变更。而命令模式则不同,它关注命令的实现,也就是功能的实现。例如接收者的变更问题,它只影响到命令族的变更,对请求者没有任何影响,从这方面来说,接收者对命令负责,而与请求者无关。命令模式中的接收者只要符合六大设计原则,完全不用关心它是否完成了一个具体逻辑,它的影响范围也仅仅是抽象命令和具体命令,对它的修改不会扩散到模式外的模块。
策略模式对付的问题域通常是一个,就是说,多个策略只是处理同一个问题,而命令模式对付的是多个问题域,就是很多不同的命令来做不同的事情。
public class CommandTest { public static void main(String[] args) { Command command = new ConcreteCommand(); Invoker invoker = new Invoker(command); System.out.println("客户端访问调用者的call方法"); invoker.call(); } } //调用者 class Invoker { private Command command; public Invoker(Command command) { this.command = command; } public void setCommand(Command command) { this.command = command; } public void call() { System.out.println("调用者执行命令Command"); command.execute(); } } //抽象命令 interface Command { void execute();//命令执行 } //具体命令 class ConcreteCommand implements Command { private Receiver receiver; ConcreteCommand() { receiver = new Receiver(); } public void execute() { receiver.action(); } } //命令接收者 class Receiver { public void action() { System.out.println("接收者的action方法被调用..."); } }
程序运行结果输出如下:
客户端访问调用者的call方法 调用者执行命令Command 接收者的action方法被调用...
责任链模式,又叫职责链模式,是指为了避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可以将请求沿着这条链进行传递,直到没有对象处理它为止。现实情境中的审批流程、请假流程等都是责任链模式。
责任链模式的关键在于通过在抽象处理者类中封装next对象,从而实现处理者之间的链式串联。当请求发起时,处理者对象通过封装的责任链顺序依次向下传递匹配是否是该对象的处理职责,直到找不到下一个对象为止。组装灵活,处理有序。
责任链模式包含以下角色:抽象处理者、具体处理者、客户类。
public class ChainOfResponsibilityTest { public static void main(String[] args) { //组装责任链 Handler handler1 = new ConcreteHandler1(); Handler handler2 = new ConcreteHandler2(); handler1.setNext(handler2); //提交请求 handler1.handleRequest("two"); } } //抽象处理者角色 abstract class Handler { private Handler next; public Handler getNext() { return next; } public void setNext(Handler next) { this.next = next; } //处理请求的方法 public abstract void handleRequest(String request); } //具体处理者1 class ConcreteHandler1 extends Handler { public void handleRequest(String request) { if (request.equals("one")) { System.out.println("具体处理者1负责处理该请求"); } else { if (getNext() != null) { getNext().handleRequest(request); } else { System.out.println("没有人处理该请求!"); } } } } //具体处理者2 class ConcreteHandler2 extends Handler { public void handleRequest(String request) { if (request.equals("two")) { System.out.println("具体处理者2负责处理该请求"); } else { if (getNext() != null) { getNext().handleRequest(request); } else { System.out.println("没有人处理该请求!"); } } } }
程序运行结果输出如下:
具体处理者2负责处理该请求
状态模式是指对有状态的对象,把复杂的“判断逻辑”提取到不同的状态对象中,允许状态对象在其内部状态发生改变时改变其行为。
状态模式包含以下角色:环境类角色、抽象状态角色、具体状态角色。
状态模式的关键在于将环境类与状态类进行双向绑定,环境类中封装了状态类对象,状态类中同样封装了环境类的引用,当触发改变状态时,状态类就会通过环境类的引用调用环境类设置状态方法,从而更新环境类中的状态对象,实现状态之间的切换。
public class StateTest { public static void main(String[] args) { //创建环境 Context context = new Context(); //处理请求 context.Handle(); context.Handle(); context.Handle(); } } //环境类 class Context { private State state; //定义环境类的初始状态 public Context() { this.state = new ConcreteStateA(); } //读取状态 public State getState() { return state; } //设置新状态 public void setState(State state) { this.state = state; } //对请求进行处理 public void Handle() { state.Handle(this); } } //抽象状态类 abstract class State { public abstract void Handle(Context context); } //具体状态A class ConcreteStateA extends State { public void Handle(Context context) { System.out.println("当前状态是A"); context.setState(new ConcreteStateB()); } } //具体状态B class ConcreteStateB extends State { public void Handle(Context context) { System.out.println("当前状态是B"); context.setState(new ConcreteStateA()); } }
程序运行结果输出如下:
当前状态是A 当前状态是B 当前状态是A
本文主要参考:http://c.biancheng.net/
https://www.baidu.com/link?url=755yVIAEhq-g9LUCeSQEol8ZQyCV3Kvnz0fl7_X0vVvh2CfI1DQ_KWUQOwM-zxMwgFX-rYgBB7BEU0O-GedqEK&wd=&eqid=cf4ab4fc002723ab000000046084cf94