java - 策略模式、状态模式、卫语句,避免多重if-else(转)
前言
当代码中出现多重if-else语句或者switch语句时。弊端之一:如果这样的代码出现在多处,那么一旦出现需求变更,就需要把所有地方的if-else或者switch代码进行更改,要是遗漏了某一处,那么程序就会出错。弊端之二:代码逻辑难以理解,可读性低。
卫语句
if (isSunshine()) {
// 晴天时处理逻辑
return xx;
}
if (isRain()) {
// 下雨时处理逻辑
}
if (isOvercast()) {
// 阴天时处理逻辑
}
策略模式
使用策略模式可以代替多重if-else和switch语句,让代码维护变得更加简单。
策略模式UML:

.环境(Context)角色:持有一个Strategy的引用
.抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现
.具体策略(ConcreteStrategy)角色:包装了相关的算法或行为
策略模式代码模板
package com.zzk.test.strategy.template; import com.zzk.test.strategy.template.base.Strategy; /**
* @描述 环境角色
*/
public class Context { /**
* 策略对象
*/
private Strategy strategy; /**
* @param strategy 具体策略对象
*/
public Context(Strategy strategy) {
this.strategy = strategy;
} /**
* @描述 执行策略方法
*/
public void contextInterface() {
strategy.strategyInterface();
}
}
package com.zzk.test.strategy.template.base; /**
* @描述 抽象策略角色
*/
public interface Strategy { /**
* @描述 策略方法
*/
void strategyInterface();
}
package com.zzk.test.strategy.template; import com.zzk.test.strategy.template.base.Strategy; /**
* @描述 具体策略类A
*/
public class ConcreteStrategyA implements Strategy { @Override
public void strategyInterface() {
// TODO Auto-generated method stub
}
}
package com.zzk.test.strategy.template; import com.zzk.test.strategy.template.base.Strategy; /**
* @描述 具体策略类B
*/
public class ConcreteStrategyB implements Strategy { @Override
public void strategyInterface() {
// TODO Auto-generated method stub
}
}
package com.zzk.test.strategy.template; import com.zzk.test.strategy.template.base.Strategy; /**
* @描述 具体策略类C
*/
public class ConcreteStrategyC implements Strategy { @Override
public void strategyInterface() {
// TODO Auto-generated method stub
}
}
调用者
/**
* @描述 使用策略模式:针对一组算法,将每一个算法封装到具有共同接口的独立的类
*/
public static void useStrategy() {
// 具体使用策略
Strategy strategy = new ConcreteStrategyA();
// 将策略放入环境中并执行策略
new Context(strategy). contextInterface();
}
状态模式
状态模式类图

环境(Context)角色,也成上下文:定义客户端所感兴趣的接口,并且保留一个具体状态类的实例。这个具体状态类的实例给出此环境对象的现有状态
抽象状态(State)角色:定义一个接口,用以封装环境(Context)对象的一个特定的状态所对应的行为
具体状态(ConcreteState)角色:每一个具体状态类都实现了环境(Context)的一个状态所对应的行为
策略模式代码模板:
package xyz.zeling.test.state.template.base; /**
* @description 抽象状态角色
* @author zeling
* @date 2018年1月14日 下午8:41:14
*/
public interface State { /**
* @description 处理方法
* @date 2018年1月14日 下午8:41:00
*/
void handle();
}
package xyz.zeling.test.state.template; import xyz.zeling.test.state.template.base.State; /**
* @description 具体状态类A
* @author zeling
* @date 2018年1月14日 下午8:45:00
*/
public class ConcreteStateA implements State { @Override
public void handle() {
// TODO Auto-generated method stub
}
}
package xyz.zeling.test.state.template; import xyz.zeling.test.state.template.base.State; /**
* @description 具体状态类A
* @author zeling
* @date 2018年1月14日 下午8:45:00
*/
public class ConcreteStateB implements State { @Override
public void handle() {
// TODO Auto-generated method stub
}
}
package xyz.zeling.test.state.template; import xyz.zeling.test.state.template.base.State; /**
* @description 具体状态类A
* @author zeling
* @date 2018年1月14日 下午8:45:00
*/
public class ConcreteStateC implements State { @Override
public void handle() {
// TODO Auto-generated method stub
}
}
package xyz.zeling.test.state.template; import xyz.zeling.test.state.template.base.State; /**
* @description 状态模式,环境角色类
* @author zeling
* @date 2018年1月14日 下午8:43:58
*/
public class Context { /**
* 状态对象
*/
private State state; /**
* @description 设置状态
* @date 2018年1月14日 下午9:13:20
* @param state 具体状态
*/
public void setState(State state) {
this.state = state;
} /**
* @description 执行策略方法
* @date 2018年1月14日 下午8:43:31
*/
public void request() {
state.handle();
}
}
调用者
/**
* @description 使用状态模式:状态模式,又称状态对象模式(Pattern of Objects for
* States),状态模式是对象的行为模式。状态模式允许一个对象在其内部状态改变的时候改变其行为。这个对象看上去就像是改变了它的类一样
* @date 2018年1月14日 下午4:04:16
*/
public static void useState() {
// 具体使用状态
State state = new ConcreteStateA();
// 创建环境
Context context = new Context();
// 设置状态并执行
context.setState(state);
context.print();
}
策略模式和状态模式的比较
讲真,我觉得它们都差不多啊,好难区别啊!!!
不过,虽然讲不出来它们的区别是什么,但是有个例子可以很好的描述它们的区别
.状态模式:这个模式就好比员工申请离职单的流程,离职单到直接上级,这个状态就是直接上级批示,等直接上级审阅之后,通过了就到下一个状态。这一个个状态对应不同的处理,这是有顺序要求的。
.策略模式:这个模式好比于你假期要出国游玩,有日本、美国、新加坡等国家,你每到一个国家就执行不同的游玩策略,可以先去日本,也可以先去美国,没有顺序要求。
java - 策略模式、状态模式、卫语句,避免多重if-else(转)的更多相关文章
- JAVA设计模式:状态模式
声明:转载请说明来源:http://www.cnblogs.com/pony1223/p/7518226.html 一.引出状态模式 假设我们现在有一个糖果机项目,那么我们知道正常一般糖果机提供给用户 ...
- 折腾Java设计模式之状态模式
原文地址 折腾Java设计模式之状态模式 状态模式 在状态模式(State Pattern)中,类的行为是基于它的状态改变的.这种类型的设计模式属于行为型模式.在状态模式中,我们创建表示各种状态的对象 ...
- Java设计模式(十) 备忘录模式 状态模式
(十九)备忘录模式 备忘录模式目的是保存一个对象的某个状态,在适当的时候恢复这个对象. class Memento{ private String value; public Memento(Stri ...
- 曾侯乙编钟引发的遐想之Java设计模式:状态模式
目录 示例 简单例子 改进代码 状态模式 定义 意图 主要解决问题 何时使用 优缺点 曾侯乙编钟 状态模式-命令模式-策略模式 示例 一个类对外提供了多个行为,同时该类对象有多种状态,不同状态下对外的 ...
- JAVA设计模式--State(状态模式)
状态模式(State Pattern)是设计模式的一种,属于行为模式. 定义(源于Design Pattern):当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类. 状态模式主要 ...
- java设计模式--行为型模式--状态模式
什么是行为型模式,小编觉得就是对行为的一种描述啦,一种对某种行为模型的定义. 状态模式: 状态模式 概述 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被 ...
- Java设计模式之状态模式详解
(本文由言念小文原创,转载请注明出处) 在实际工作中经常遇到某个对象,处于不同的状态有不同行为逻辑.且状态之间可以相互迁移的业务场景,特别是在开发通信协议栈类软件中尤为多见.<设计模式之禅> ...
- java设计模式之状态模式
状态模式 允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类. 状态模式UML图 上下文环境(Context):它定义了客户程序需要的接口并维护一个具体状态角色的实例,将与状态相关 ...
- [19/05/02-星期四] GOF23_行为型模式(状态模式、观察者模式、备忘录模式)
一.状态模式 [状态接口] /*** * 房间"状态"接口 */ package cn.sxt.state; public interface State { void handl ...
- 8.js模式-状态模式
1. 状态模式 var offLightState = function(light){ this.light = light; } offLightState.prototype.buttonWas ...
随机推荐
- MessengerJS
跨文档通信解决方案 Since modern browsers have native cross-document communication method(the PostMeessage API ...
- Java中几个常用类
1.1 包装类 把八大基本数据类型封装到一个类中,并提供属性和方法,更方便的操作基本数据类型. 包装类的出现并不是用于取代基本数据类型,也取代不了. 包装类位于java.lang包中 Number 类 ...
- 北京大学Cousera学习笔记--4-计算导论与C语言基础--计算机的基本原理-程序运行的基本原理
已知:电路能完成计算 怎么计算:设计好很多个原子电路,需要的时候就把他们临时组装在一起--ENIAC 升级:冯诺依曼-EDVAC(现在的计算机都是) 1.通过某种命令来控制计算机.让计算机按照这种命令 ...
- CSS常见兼容问题以及解决办法
浏览器的兼容性问题,通常是因为不同的浏览器对同一段代码有不同的解析,造成页面显示不统一的情况. 这里谈到的浏览器,主要指IE6/IE7/IE... FireFox Chrome Opera Safar ...
- python值json与pickle模块
#json 是用来序列化对象的 # 只有2个方法,序列化与反序列化 # 但是不能序列化类 与 函数 import json dict={"key1":[1,2,3,4,5]} f ...
- No module named 'pip._internal'
报错: Traceback (most recent call last):File "/home/myuser/.local/bin/pip", line 7, in <m ...
- Installing ROS Indigo on the Raspberry Pi
Installing ROS Indigo on the Raspberry Pi Description: This instruction covers the installation of R ...
- Android配置AndroidAnnotations注解框架配置
1在新建的普通项目里面,新建一个compile-libs文件夹,将下载来的androidannotation-xx.jar添加到compile-libs文件夹下,将androidannotation- ...
- Hibernate的load和get方法的区别
这次我们聊一下Hibernate3.2 Session加载数据时get和load方法的区别,我总结的如下: 1. 对于get方法,hibernate会确认一下该id对应的数据是否存在,首先在sessi ...
- UML类图新手入门级介绍(转)
首先,看动物矩形框,它代表一个类(Class).类图分三层,第一层显示类的名称,如果是抽象类,则就用斜体显示.第二层是类的特性,通常就是字段和属性.第三层是类的操作,通常是方法或行为.前面的符号,+ ...