设计模式之禅PK之行为类
行为类设计模式
- 行为类模式:
- 责任链模式
- 命令模式
- 迭代器模式
- 中介者模式
- 备忘录模式
- 观察者模式
- 状态模式
- 策略模式
- 模板方法模式
- 访问者模式
【策略模式】VS【状态模式】
- 在行为类设计模式中,状态模式和策略模式是亲兄弟,两者都非常的相似。那先看看他们的不同吧
类图
策略模式 | 状态模式 |
---|---|
- 两个类图非常的相似,都是通过Context类封装一个具体的行为,都提供了一个封装的方法,是高扩展的设计模式。根据两个模式的定义,看看这两者的区别
区别项 | 策略模式 | 状态模式 |
---|---|---|
封装的对象 | 封装的是不同的算法,算法之间没有交互,已达到算法可以自由切换的目的 | 封装的是不同的状态,已达到状态切换为之发生改变的目的, |
目标 | 不同的人生阶段,有着不同的生活方式:小时候玩耍、成人时期的工作和老年的享受天伦之乐----之间用到的算法大概有这么几种:冒泡排序、快速排序、插入排序。。。 | 状态的模式:人的一生的状态---儿童、成人、老人 |
以人生的实现来将代码码一下
- 还是先来看看两者的类图吧
策略模式 | 状态模式 |
---|---|
-
策略模式实现人生
-
WorkAlgorithm
package com.peng.pk_cl2; /** * @author kungfu~peng * @data 2017年12月14日 * @description */ public abstract class WorkAlgorithm { // 每个阶段都必须完成的任务 public abstract void work(); }
-
ChildWork
package com.peng.pk_cl2; /** * @author kungfu~peng * @data 2017年12月14日 * @description */ public class ChildWork extends WorkAlgorithm { @Override public void work() { System.out.println("儿童时期的工作是玩耍!"); } }
-
AdultWork
package com.peng.pk_cl2; /** * @author kungfu~peng * @data 2017年12月14日 * @description */ public class AdultWork extends WorkAlgorithm { @Override public void work() { System.out.println("成年的任务是工作!"); } }
-
OldWork
package com.peng.pk_cl2; /** * @author kungfu~peng * @data 2017年12月14日 * @description */ public abstract class WorkAlgorithm { // 每个阶段都必须完成的任务 public abstract void work(); }
-
Context
package com.peng.pk_cl2; /** * @author kungfu~peng * @data 2017年12月14日 * @description */ public class Context { private WorkAlgorithm workMethod; public WorkAlgorithm getWorkMethod() { return workMethod; } public void setWorkMethod(WorkAlgorithm workMethod) { this.workMethod = workMethod; } // 每个算法都必须具有的功能 public void work() { workMethod.work(); } }
-
Client
package com.peng.pk_cl2; /** * @author kungfu~peng * @data 2017年12月14日 * @description */ public class Client { public static void main(String[] args) { // 定义一个环境角色 Context context = new Context(); System.out.println("=====儿童的主要工作====="); context.setWorkMethod(new ChildWork()); context.work(); System.out.println("=====成年的主要工作====="); context.setWorkMethod(new AdultWork()); context.work(); System.out.println("=====老年的主要工作====="); context.setWorkMethod(new OldWork()); context.work(); } }
-
执行结果
=====儿童的主要工作===== 儿童时期的工作是玩耍! =====成年的主要工作===== 成年的任务是工作! =====老年的主要工作===== 老年的任务是享受天伦之乐!
-
-
状态模式实现人生
-
Human
package comp.peng.pk_zt; /** * @author kungfu~peng * @data 2017年12月14日 * @description */ public class Human { // 定义人都具有具备哪些状态 public static final HumanState CHILD_STATE = new ChildrenState(); public static final HumanState Adult_STATE = new AdultState(); public static final HumanState Old_STATE = new OldState(); // 定义一个人的状态 private HumanState state; // 设置一个状态 public void setState(HumanState state) { this.state = state; } // 人类的工作 public void work() { this.state.work(); } }
-
HumanState
package comp.peng.pk_zt; /** * @author kungfu~peng * @data 2017年12月14日 * @description */ public abstract class HumanState { // 指向一个具体的人 protected Human human; // 设置一个具体的人 public void setHuman(Human human) { this.human = human; } // 不管什么状态都要工作 public abstract void work(); }
-
ChildrenState
package comp.peng.pk_zt; /** * @author kungfu~peng * @data 2017年12月14日 * @description */ public class ChildrenState extends HumanState { @Override public void work() { System.out.println("儿童:玩耍!"); } }
-
AdultStat
package comp.peng.pk_zt; /** * @author kungfu~peng * @data 2017年12月14日 * @description */ public class AdultState extends HumanState{ @Override public void work() { System.out.println("成年:工作!"); } }
-
OldState
package comp.peng.pk_zt; /** * @author kungfu~peng * @data 2017年12月14日 * @description */ public class OldState extends HumanState { @Override public void work() { System.out.println("老年:享受天伦之乐!"); } }
-
Client
package comp.peng.pk_zt; /** * @author kungfu~peng * @data 2017年12月14日 * @description */ public class Client { public static void main(String[] args) { // 定义一个普通的人 Human human = new Human(); // 设置一个初始状态 human.setState(new ChildrenState()); System.out.println("=====儿童的主要工作====="); human.work(); // 设置一个初始状态 human.setState(new AdultState()); System.out.println("=====成人的主要工作====="); human.work(); // 设置一个初始状态 human.setState(new OldState()); System.out.println("=====老年的主要工作====="); human.work(); } }
-
执行结果
=====儿童的主要工作===== 儿童:玩耍! =====成人的主要工作===== 成年:工作! =====老年的主要工作===== 老年:享受天伦之乐!
-
-
运行结果与策略模式相同,但是两者的分析角度是大相径庭的。策略模式的实现是通过分析每个人的工作方式的不同而得出三个不同的算法逻辑;状态模式则是从人的生长规律来分析,每个状态对应了不同的行为,状态改变后行为也随之改变
最佳实践
- 从上述的例子中不难看出,策略模式和状态模式称之为兄弟也不为过,但是这两者还是存在着非常大的差别,而且也是很容易区分的
比较项 | 策略模式 | 装饰模式 |
---|---|---|
环境角色的职责 | 只是一个委托作用,负责算法的替换 | 不仅仅是委托行为,它还具有登记状态变化的功能,与具体的状态类协作,共同完成状态切换行为为随之切换的任务 |
解决的问题重点 | 解决内部算法如何改变的问题--将内部算法的改变时对外界的影响降到最低,它是保证算法可以自由的切换 | 解决内在状态的改变而引起行为改变的问题,它的出发点是事务的状态,封装状态而暴露行为,一个对象状态的改变,从外界看就像是行为的改变 |
解决问题的方法 | 确保算法可以自由切换,但是什么时候用算法它决定不了 | 对外暴露的行为,状态的变化一般是由环境角色和具体的状态共同完成的,也就是说状态模式封装了状态的变化而暴露了不同的行为或行为结果 |
应用场景 | 可以是一个有意义的对象;也可以是无意义的逻辑片段。【eg:MD5加密,DES算法,RSA算法】 | 一系列状态变化的场景,要求一个对象必须具有二维【状态和行为】 |
复杂度不同 | 结构比较简单,扩展比较容易 | 通常比较复杂 |
声明
- 摘自秦小波《设计模式之禅》第2版;
- 仅供学习,严禁商业用途;
- 代码手写,没有经编译器编译,有个别错误,自行根据上下文改正;