Java设计模式之策略模式与状态模式
版权声明:本文出自汪磊的博客,转载请务必注明出处。
一、策略模式定义
定义:策略模式定义了一系列的算法,并将每一个算法封装起来,而且使他们之间可以相互替换,策略模式可以在不影响客户端的情况下发生变化。
好了,定义看看就完了,我知道你很烦看定义。
二、策略模式涉及到的三个角色
环境(Context)角色 持有一个Strategy的引用
抽象策略(Strategy)角色 这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
具体策略(ConcreteStrategy)角色 包装了具体的算法或行为。
三、策略模式使用举例
还是赶快看代码吧,知道你看上面定义都烦死了。
我们写一个简单的Demo来对策略模式进行更深的理解,我们模拟游戏中玩家参与一个活动购买金币,普通玩家没有折扣,高级玩家9折优惠,VIP玩家7折优惠。
首先我们定义一个接口,这就是抽象策略角色,如下:
public interface GameStrategy {
public void goldCoin();
}
很简单,就是一个接口。
接下来我们编写具体策略角色类,从需求就能明白,需要有三个具体策略角色类,也就是三个策略对应不同等级玩家。
普通玩家策略类:
public class normalStrategy implements GameStrategy {
@Override
public void goldCoin() {
//
System.out.println("普通玩家没有折扣");
}
}
高级玩家策略类:
public class advancedStrategy implements GameStrategy {
@Override
public void goldCoin() {
// TODO Auto-generated method stub
System.out.println("高级会员9折优惠");
}
}
VIP玩家策略类:
public class vipStrategy implements GameStrategy {
@Override
public void goldCoin() {
//
System.out.println("VIP会员7折优惠");
}
}
都很简单,就是简单打印信息。
然后编写环境角色类,如下:
public class Context {
//持有一个Strategy的引用
private GameStrategy mGameStrategy;
// 构造函数
public Context(GameStrategy strategy) {
this.mGameStrategy = strategy;
}
public void setStrategy(GameStrategy strategy) {
this.mGameStrategy = strategy;
}
public void goldCoin() {
this.mGameStrategy.goldCoin();
}
}
最后就是调用了,根据不同情况调用不同策略:
public class main {
public static void main(String[] args) {
//普通玩家策略
Context context = new Context(new normalStrategy());
context.goldCoin();
//高级玩家策略
context.setStrategy(new advancedStrategy());
context.goldCoin();
//高级玩家策略
context.setStrategy(new vipStrategy());
context.goldCoin();
}
}
不同情况下我们替换为对应策略就可以了。
四、策略模式优缺点
优点
策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族。恰当使用继承可以把公共的代码移到父类里面,从而避免代码重复。使用策略模式可以避免使用多重条件(if-else)语句。多重条件语句不易维护,它把采取哪一种算法让子类实现
缺点
通过上面Demo我们会发现调用者必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类并且由于策略模式把每个具体的策略实现都单独封装成为类,如果备选的策略很多的话,那么对象的数目就会很可观。
好了上面就是策略模式的介绍了,关键是自己慢慢理解。接下来我们了解一下状态模式。
五、状态模式定义
当一个对象在其内部状态改变的时候改变其行为。这个对象看上去就像是改变了它的类一样。又称状态对象模式,状态模式是对象的行为模式。
简单的理解就是一个类其状态改变了,那么其功能也相应的改变了。比如水变为冰,状态改变了,其功能也发生了相应变化。
六、状态模式角色
● Context(环境类):环境类又称为上下文类,它是拥有多种状态的对象。由于环境类的状态存在多样性且在不同状态下对象的行为有所不同,因此将状态独立出去形成单独的状态类。在环境类中维护一个抽象状态类State的实例,这个实例定义当前状态,在具体实现时,它是一个State子类的对象。
● State(抽象状态类):它用于定义一个接口以封装与环境类的一个特定状态相关的行为,在抽象状态类中声明了各种不同状态对应的方法,而在其子类中实现类这些方法,由于不同状态下对象的行为可能不同,因此在不同子类中方法的实现可能存在不同,相同的方法可以写在抽象状态类中。
● ConcreteState(具体状态类):它是抽象状态类的子类,每一个子类实现一个与环境类的一个状态相关的行为,每一个具体状态类对应环境的一个具体状态,不同的具体状态类其行为有所不同。
七、状态模式使用举例
接下来我们编写一个小Demo来进行更深入理解:在办公系统中,一个文件会有不同状态:未处理,正在处理,已经处理。我们就简单模拟一下文件状态的切换。
首先我们看下抽象状态类,很简单就是定义一个接口:
public interface State {
void fileState();
}
接下来看下三个具体状态类:
未处理状态类
public class NotDealState implements State{
@Override
public void fileState() {
// TODO Auto-generated method stub
System.out.println("文件未处理状态");
}
}
正在处理状态类:
public class DealingState implements State{
@Override
public void fileState() {
// TODO Auto-generated method stub
System.out.println("文件正在处理状态");
}
}
已经处理状态类
public class HasDealState implements State{
@Override
public void fileState() {
// TODO Auto-generated method stub
System.out.println("文件已经处理状态");
}
}
是不是很简单,同样也只是打印一些简单的信息罢了。
然后看下上下文类:
public class FileContext {
//默认情况下未处理状态
private State fileState = new NotDealState();
/**
* 文件状态切换为未处理状态
*/
public void notDeal(){
this.fileState = new NotDealState();
}
/**
* 文件状态切换为正在处理状态
*/
public void Dealing(){
this.fileState = new DealingState();
}
/**
* 文件状态切换为已经处理状态
*/
public void HasDeal(){
this.fileState = new HasDealState();
}
/**
* 获取当前文件的状态
*/
public void getFileState(){
fileState.fileState();
}
}
上下文类主要就是封装当前文件状态并且对外提供状态切换的方法
最后看下怎么使用吧:
public class Client {
public static void main(String[] args) {
FileContext fileContext = new FileContext();
fileContext.getFileState();
//切换为正在处理状态
fileContext.Dealing();
fileContext.getFileState();
//切换为已经处理状态
fileContext.HasDeal();
fileContext.getFileState();
}
}
外部使用调用相应切换状态方法就可以了,很简单,没有什么需要特别说明的。
八、状态模式与策略模式区别以及联系
策略模式与状态模式及其相似,但是二者有其内在的差别,策略模式将具体策略类暴露出去,调用者需要具体明白每个策略的不同之处以便正确使用。而状态模式状态的改变是由其内部条件来改变的,与外界无关,二者在思想上有本质区别。
好了,状态模式与策略模式讲解到此为止,二者区别联系不是几句话就能说清楚,关键是思想上的不同,具体感悟需要在实践中自己慢慢体会。
Java设计模式之策略模式与状态模式的更多相关文章
- Java进阶篇设计模式之十二 ---- 备忘录模式和状态模式
前言 在上一篇中我们学习了行为型模式的策略模式(Strategy Pattern)和模板模式(Template Pattern).本篇则来学习下行为型模式的两个模式,备忘录模式(Memento Pat ...
- 【设计模式】 模式PK:策略模式VS状态模式
1.概述 行为类设计模式中,状态模式和策略模式是亲兄弟,两者非常相似,我们先看看两者的通用类图,把两者放在一起比较一下. 策略模式(左)和状态模式(右)的通用类图. 两个类图非常相似,都是通过Cont ...
- 设计模式之第21章-状态模式(Java实现)
设计模式之第21章-状态模式(Java实现) “what are you 干啥了?怎么这么萎靡不振?”“昨晚又是补新番,又是补小笼包,睡得有点晚啊.话说杨过的那个雕兄真是太好了,每天给找蛇胆,又陪练武 ...
- 设计模式之策略模式和状态模式(strategy pattern & state pattern)
本文来讲解一下两个结构比较相似的行为设计模式:策略模式和状态模式.两者单独的理解和学习都是比较直观简单的,但是实际使用的时候却并不好实践,算是易学难用的设计模式吧.这也是把两者放在一起介绍的原因,经过 ...
- Java 策略模式和状态模式
本文是转载的,转载地址:大白话解释Strategy模式和State模式的区别 先上图: 本质上讲,策略模式和状态模式做得是同一件事:去耦合.怎么去耦合?就是把干什么(语境类)和怎么干(策略接口)分开, ...
- java - 策略模式、状态模式、卫语句,避免多重if-else(转)
前言 当代码中出现多重if-else语句或者switch语句时.弊端之一:如果这样的代码出现在多处,那么一旦出现需求变更,就需要把所有地方的if-else或者switch代码进行更改,要是遗漏了某一处 ...
- Java设计模式之十二 ---- 备忘录模式和状态模式
前言 在上一篇中我们学习了行为型模式的策略模式(Strategy Pattern)和模板模式(Template Pattern).本篇则来学习下行为型模式的两个模式,备忘录模式(Memento Pat ...
- Java重构-策略模式、状态模式、卫语句
前言 当代码中出现多重if-else语句或者switch语句时.弊端之一:如果这样的代码出现在多处,那么一旦出现需求变更,就需要把所有地方的if-else或者switch代码进行更改,要是遗漏了某一处 ...
- 【转】Java重构-策略模式、状态模式、卫语句
前言 当代码中出现多重if-else语句或者switch语句时.弊端之一:如果这样的代码出现在多处,那么一旦出现需求变更,就需要把所有地方的if-else或者switch代码进行更改,要是遗漏了某一处 ...
随机推荐
- deeplearning.ai 人工智能行业大师访谈 Yoshua Bengio 听课笔记
1. 如何走上人工智能的研究的?Bengio说他小时候读了很多科幻小说,1985年(64年出生,21岁)研究生阶段开始阅读神经网络方面的论文,对这个领域产生了热情. 2. 如何看深度学习这些年的发展? ...
- [译]Dapper教程
脑子里突然浮现出一个想法:尝试翻译一些技术文档.说干就干,先来翻译个最近经常查阅的Dapper教程,有兴趣的园友可以一起参与进来 dapper-tutorial-cn. 什么是Dapper Dappe ...
- 2017 年“认证杯”数学中国数学建模网络挑战赛 C题思路讲解
之前有小伙伴私信我叫我说说这次比赛C题的思路,怎么写的,我就写篇博客说说吧,仅供参考! 针对C题,该题目比较综合,是一个成熟的数模赛题,与国赛的相似性较高.一般而言,第一问难度较低,题目要求进行数据挖 ...
- 【笔记】移动端H5数字键盘input type=number的处理(IOS和Android)
在Vue中的项目,基于VUX-UI开发,一个常见的需求: 1.金额输入框 2.弹出数字键盘 3.仅支持输入两位小数,限制最大11位数,不允许0开头 后续:与UI沟通后, 思路调整为限制输入,并减少正则 ...
- div排版+文档流+定位秘诀
由于没有找到自己认为完整的关于普通流.浮动和绝对定位的中文文章,于是鼓起勇气决定自己来写篇. 在普通流中的 Box(框) 属于一种 formatting context(格式化上下文) ,类型可以是 ...
- Spark_总结七_troubleshooting
转载标明出处 http://www.cnblogs.com/haozhengfei/p/07ef4bda071b1519f404f26503fcba44.html Spark_总结七_troubles ...
- 简单易用的IT运维服务器管理程序
程序修改历史: 2012.02.04 v1.0 leopku 2012.02.09 v1.1 oldboy(老男孩) QQ:31333741 MAIL:oldboy521@gmail.com 本软件由 ...
- phpMyAdmin访问远程MySQL数据库的方法
本地phpmyadmin远程连接服务器端MySQL 首先要确定你的mysql远程连接已开启,如果没有开启按照下面的二个方法操作: 方法一:改表法 因为在linux环境下,默认是关闭3306端口远程连接 ...
- 关于Spring的69个面试题
这篇文章总结了一些关于Spring框架的重要问题,这些问题都是你在面试或笔试过程中可能会被问到的.下次你再也不用担心你的面试了,Java Code Geeks这就帮你解答. 大多数你可能被问到的问题都 ...
- J.U.C atomic 数组,字段原子操作
这里看一下原子数组操作和一些其他的原子操作. AtomicIntegerArray/AtomicLongArray/AtomicReferenceArray的API类似,选择代表性的AtomicInt ...