在上一篇中咱们学习了行为型模式的策略模式(Strategy Pattern)和模板模式(Template Pattern)。本篇则来学习下行为型模式的两个模式,备忘录模式(Memento Pattern)和状态模式(Memento Pattern)。html
简介java
备忘录模式(Memento Pattern)用于保存一个对象的某个状态,以便在适当的时候恢复对象,该模式属于行为型模式。
其主要目的是在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象以外保存这个状态。git
备忘录模式,其主要的的思想就是备份。例如,txt、word等文档的保存,游戏的存档,操做系统的备份,也包括咱们常常用的快捷键Ctrl+Z等等。除了以上的这些应用,咱们在编程中接触最多的估计就是数据库的事物了,它提供了一种恢复机制,可在出现异常的时候进行还原。github
备忘录模式主要由这三个角色组成,备忘录角色(Memento)、发起人角色(Originator)和负责人(Caretaker)角色。数据库
示例图以下:
编程
咱们这里依旧用一个示例来进行说明吧。
咱们在玩游戏有的时候,会常常用到一个游戏功能,那就是存档。主要是为了保存游戏进度,防止信息丢失,而且也能够经过进行读档恢复保存的信息。好比xuwujing在玩一个游戏的时候,建立好角色以后进行打怪练级,而后挑战BOSS,不过担忧挑战失败,因而便在挑战前进行存档,存档成功以后,再来进行挑战BOSS。
那么咱们能够根据这个场景来使用备忘录模式来进行开发。网络
首先定义一个Memento,也就是游戏存档的信息,主要存储游戏人物等级和生命值。ide
class SaveMsg{ private int level; private int life; public SaveMsg( int level, int life) { super(); this.level = level; this.life = life; } public int getLevel() { return level; } public void setLevel(int level) { this.level = level; } public int getLife() { return life; } public void setLife(int life) { this.life = life; } }
而后再定义一个Originator,这里就是玩家了,除了等级和生命值信息外,玩家还能够进行存档、读档,以及进行一些活动,打怪练级和挑战BOSS。学习
那么代码以下:测试
class Player { //等级 private int level; //生命值 private int life; public Player( int level, int life) { super(); this.level = level; this.life = life; } //保存信息 public SaveMsg saveStateToMemento() { return new SaveMsg(level,life); } //恢复信息 public void getStateFromMemento(SaveMsg sm) { this.level = sm.getLevel(); this.life = sm.getLife(); } //获取当前状态 public void getStatus() { System.out.println("玩家xuwujing当前信息:"); System.out.println("人物等级:"+level+",人物生命:"+life); } //练级 public void leveling() { this.level = this.level+1; this.life = this.life+10; System.out.println("恭喜玩家xuwujing升级!等级提高了1,生命提高了10!"); } //挑战BOSS public boolean challengeBOSS() { //设置条件 return this.level>2&&this.life>100; } }
最后在定义一个Caretaker,做为游戏存档页,用于保存存档信息。
代码以下:
class GameSavePage{ private SaveMsg sm; public SaveMsg getSm() { return sm; } public void setSm(SaveMsg sm) { this.sm = sm; } }
编写好以后,那么咱们来进行测试。
相应的测试代码以下:
public static void main(String[] args) { int level = 1; int life = 100; //建立一个玩家 Player player =new Player(level, life); System.out.println("玩家xuwujing进入游戏!"); //状态 player.getStatus(); //进行练级 player.leveling(); GameSavePage savePage =new GameSavePage(); //状态 player.getStatus(); System.out.println("玩家xuwujing正在存档..."); //第一次存档 savePage.setSm(player.saveStateToMemento()); System.out.println("玩家xuwujing存档成功!"); System.out.println("玩家xuwujing挑战新手村的BOSS!"); boolean flag=player.challengeBOSS(); if(flag) { System.out.println("玩家xuwujing挑战BOSS成功!"); return; } System.out.println("玩家xuwujing挑战BOSS失败!游戏结束!开始读取存档..."); savePage.getSm(); System.out.println("玩家xuwujing读取存档成功!"); //进行练级 player.leveling(); //状态 player.getStatus(); System.out.println("玩家xuwujing挑战新手村的BOSS!"); flag=player.challengeBOSS(); if(flag) { System.out.println("玩家xuwujing挑战BOSS成功!"); return; } }
输出结果:
玩家xuwujing进入游戏! 玩家xuwujing当前信息: 人物等级:1,人物生命:100 恭喜玩家xuwujing升级!等级提高了1,生命提高了10! 玩家xuwujing当前信息: 人物等级:2,人物生命:110 玩家xuwujing正在存档... 玩家xuwujing存档成功! 玩家xuwujing挑战新手村的BOSS! 玩家xuwujing挑战BOSS失败!游戏结束!开始读取存档... 玩家xuwujing读取存档成功! 恭喜玩家xuwujing升级!等级提高了1,生命提高了10! 玩家xuwujing当前信息: 人物等级:3,人物生命:120 玩家xuwujing挑战新手村的BOSS! 玩家xuwujing挑战BOSS成功!
备忘录模式优势
给用户提供了一种能够恢复状态的机制,可使用户可以比较方便地回到某个历史的状态;
实现了信息的封装,使得用户不须要关心状态的保存细节;
备忘录模式缺点
很是的消耗资源;
客户端必须知道全部的策略类才能进行调用;
使用场景:
须要保存/恢复数据的相关状态场景;
简介
状态模式(State Pattern)属于行为型模式,其状态的对象和一个行为随着状态对象改变而改变。
其主要目的解决的是当控制一个对象状态转换的条件表达式过于复杂是的状况。把状态的判断逻辑转移到表示不一样状态一系列类中,能够把复杂的判断简单化。
状态模式,其主要的的思想就是提供一种状态,提供给客户端进行调用。状态可谓无处不在,不管是电脑、手机等电子产品的开机和关机的状态,仍是常常用到的网络在线和离线状态,即便是在咱们编程中Tcp也有建立、监听、关闭状态。
状态模式主要由环境角色(Context)、 抽象状态(State)和具体状态(Concrete State)组成。
环境角色(Context): 它定义了客户程序须要的接口并维护一个具体状态角色的实例,将与状态相关的操做委托给当前的具体状态对象来处理。
具体状态角色(Concrete State):实现抽象状态定义的接口。
示例图以下:
这里为了方便理解,咱们依旧使用一个简单的示例来加以说明。
咱们在使用耳机听音乐的时候,通常会有两个状态,播放和暂停,按一下是从暂停到播放,再按一下就是从播放到暂停。那么咱们能够根据这个场景来使用状态模式进行开发!
首先依旧定义一个抽象状态角色,用于表示音乐的状态,并指定该类的行为,也就是方法,这个抽象类的代码以下:
interface MusicState{ void press(); }
定义好该抽象类以后,咱们再来定义具体状态角色类。这里定义两个状态,一个是播放状态,一个是暂停状态,代码以下:
class PlayState implements MusicState{ @Override public void press() { System.out.println("播放音乐!"); } } class PauseState implements MusicState{ @Override public void press() { System.out.println("暂停音乐!"); } }
而后在来定义一个环境角色,用于对客户端提供一个接口,并对状态进行处理。代码以下:
class Headset{ private MusicState state; private int i; public Headset(MusicState state){ this.state=state; } public void press() { if((i&1)==0) { this.state=new PlayState(); }else { this.state=new PauseState(); } this.state.press(); i++; } public MusicState getState() { return state; } public void setState(MusicState state) { this.state = state; } }
最后再来进行测试,测试代码以下:
public static void main(String[] args) { Headset hs = new Headset(new PlayState()); //第一次播放音乐 hs.press(); //第二次暂停音乐 hs.press(); //第三次播放音乐 hs.press(); }
输出结果:
播放音乐! 暂停音乐! 播放音乐!
状态模式优势:
扩展性好,将和状态有关的行为放到一块儿,增长新的的状态,只须要改变对象状态便可改变对象的行为便可;
复用性好,让多个环境对象共享一个状态对象,从而减小系统中对象的个数;
状态模式缺点:
使用状态模式会增长系统类和对象的个数,而且该模式的结构与实现都较为复杂,若是使用不当将致使程序结构和代码的混乱;
状态模式对"开闭原则"的支持并不太好,对于能够切换状态的状态模式,增长新的状态类须要修改那些负责状态转换的源代码,不然没法切换到新增状态,并且修改某个状态类的行为也需修改对应类的源代码。
使用场景:
行为随状态改变而改变的场景;
条件、分支语句的代替者。
注意事项 :
在行为受状态约束的时候使用状态模式,并且状态不超过5个。
** 和策略模式比较:**
在学习状态模式的时候,很容易和策略模式搞混,由于它们实在是太像了,很难区分,在查阅一番资料以后,整理了以下的相同点和区别点。
相同点:
区别点
分享一首很是有感触的轻音乐,虽然孤独,可是不寂寞!
网易云网友评论:
轻吟一句情话,执笔一副情画。 绽开一地情花,覆盖一片青瓦。 共饮一杯清茶,同研一碗青砂。
挽起一面轻纱,看清天边月牙。爱像水墨青花,何惧刹那芳华。
java-study是本人在学习Java过程当中记录的一些代码,也包括以前博文中使用的代码。若是感受不错,但愿顺手给个start,固然若是有不足,也但愿提出。
github地址: https://github.com/xuwujing/java-study
原创不易,若是感受不错,但愿给个推荐!您的支持是我写做的最大动力! 版权声明: 做者:虚无境 博客园出处:http://www.cnblogs.com/xuwujing CSDN出处:http://blog.csdn.net/qazwsxpcm 我的博客出处:http://www.panchengming.com