前言

当代码中出现多重if-else语句或者switch语句时。弊端之一:如果这样的代码出现在多处,那么一旦出现需求变更,就需要把所有地方的if-else或者switch代码进行更改,要是遗漏了某一处,那么程序就会出错。弊端之二:代码逻辑难以理解,可读性低。

卫语句

if (isSunshine()) {
// 晴天时处理逻辑
  return xx;
}
if (isRain()) {
// 下雨时处理逻辑
}
if (isOvercast()) {
// 阴天时处理逻辑
}

策略模式

使用策略模式可以代替多重if-elseswitch语句,让代码维护变得更加简单。 
策略模式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(转)的更多相关文章

  1. JAVA设计模式:状态模式

    声明:转载请说明来源:http://www.cnblogs.com/pony1223/p/7518226.html 一.引出状态模式 假设我们现在有一个糖果机项目,那么我们知道正常一般糖果机提供给用户 ...

  2. 折腾Java设计模式之状态模式

    原文地址 折腾Java设计模式之状态模式 状态模式 在状态模式(State Pattern)中,类的行为是基于它的状态改变的.这种类型的设计模式属于行为型模式.在状态模式中,我们创建表示各种状态的对象 ...

  3. Java设计模式(十) 备忘录模式 状态模式

    (十九)备忘录模式 备忘录模式目的是保存一个对象的某个状态,在适当的时候恢复这个对象. class Memento{ private String value; public Memento(Stri ...

  4. 曾侯乙编钟引发的遐想之Java设计模式:状态模式

    目录 示例 简单例子 改进代码 状态模式 定义 意图 主要解决问题 何时使用 优缺点 曾侯乙编钟 状态模式-命令模式-策略模式 示例 一个类对外提供了多个行为,同时该类对象有多种状态,不同状态下对外的 ...

  5. JAVA设计模式--State(状态模式)

    状态模式(State Pattern)是设计模式的一种,属于行为模式. 定义(源于Design Pattern):当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类. 状态模式主要 ...

  6. java设计模式--行为型模式--状态模式

    什么是行为型模式,小编觉得就是对行为的一种描述啦,一种对某种行为模型的定义. 状态模式: 状态模式 概述 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被 ...

  7. Java设计模式之状态模式详解

    (本文由言念小文原创,转载请注明出处) 在实际工作中经常遇到某个对象,处于不同的状态有不同行为逻辑.且状态之间可以相互迁移的业务场景,特别是在开发通信协议栈类软件中尤为多见.<设计模式之禅> ...

  8. java设计模式之状态模式

    状态模式 允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类. 状态模式UML图 上下文环境(Context):它定义了客户程序需要的接口并维护一个具体状态角色的实例,将与状态相关 ...

  9. [19/05/02-星期四] GOF23_行为型模式(状态模式、观察者模式、备忘录模式)

    一.状态模式 [状态接口] /*** * 房间"状态"接口 */ package cn.sxt.state; public interface State { void handl ...

  10. 8.js模式-状态模式

    1. 状态模式 var offLightState = function(light){ this.light = light; } offLightState.prototype.buttonWas ...

随机推荐

  1. pandas处理时间序列(3):重采样与频率转换

    五.重采样与频率转换 1. resample方法 rng = pd.date_range('1/3/2019',periods=1000,freq='D') rng 2. 降采样 (1)resampl ...

  2. DDD关键知识点整理汇总

    创建领域对象采用构造函数或者工厂,如果用工厂时需要依赖于领域服务或仓储,则通过构造函数注入到工厂: 一个聚合是由一些列相联的Entity和Value Object组成,一个聚合有一个聚合根,聚合根是E ...

  3. Java中的过滤器,拦截器,监听器---------简单易懂的介绍

    过滤器: 过滤器其主要特点在于:取你需要的东西,忽视那些不需要的东西!在程序中,你希望选择中篇文章中的所有数字,你就可以针对性的挑选数字! 拦截器: 拦截器其主要特点在于:针对你不要的东西进行拦截,比 ...

  4. Kafka笔记8(管理Kafka)

    使用kafka-topic.sh工具可以执行大部分操作   创建/修改/删除/查看集群里的主题.要使用全部功能,需要通过--zookeeper参数提供zookeerper连接字符串 创建主题: 创建主 ...

  5. Nodejs使用robot操作鼠标键盘

    1.安装robotjs库 前提是配置了cnpm cnpm i robotjs -g   2.如果报错VCBuild.exe,如下可以安装windows-tool MSBUILD : error MSB ...

  6. 利用Openssh后门 劫持root密码

    Linux操作系统的密码较难获取.而很多Linux服务器都配置了Openssh服务,在获取root权限的情况下, 可以通过修改或者更新OpenSSH代码等方法,截取并保存其SSH登录账号密码,甚至可以 ...

  7. DBC文件小结

    Vector的DBC文件描述了CAN网络的通信规范,通过定义signal可以表示CAN帧中的各个物理信号的含义.通过CANdb++ Editor软件可以创建和修改DBC文件,一般监控或控制CAN网络内 ...

  8. Django model 字段类型及选项解析---转载

    model field 类型1.AutoField() 自增的IntegerField,通常不用自己设置,若没有设置主键,Django会自动添加它为主键字段,Django会自动给每张表添加一个自增的p ...

  9. Hadoop 安全模式safemode

    启动Hdfs 系统的时候,其中的一个阶段“”安全模式 发生阶段:NameNode启动中,已经读取了fsimage 并且生成了edits 文件,在等待dataNode 向nameNode 发送block ...

  10. FineReport中日期时间函数使用总结

    说明:凡函数中以日期作为参数因子的,其中日期的形式都必须是yy/mm/dd.而且必须用英文环境下双引号(" ")引用. DATE DATE(year,month,day):返回一个 ...