【设计模式六】行为型模式(中介者/备忘录/解释器/状态)

6、中介者模式

Mediator Pattern

[ˈmiːdieɪtər]

1)基本介绍

  • 中介者模式(Mediator Pattern),用一个中介对象来封装一系列的对象交互。中介者使各个对象不需要显式地相互引用,从而使其解耦,而且可以独立地改变它们之间的交互
  • 中介者模式属于行为型模式,使代码易于维护
  • MVC模式,C(Controller控制器)是 M(Model模型)和 V(View视图)的中介者,在前后端交互时起到了中间人的作用

2)原理类图

  • Mediator 就是抽象中介者,定义了同事对象到中介者对象的接口
  • Colleague是抽象同事类
  • ConcreteMediator具体的中介者对象 ,实现抽象方法,需要知道所有的具体的同事类,即以一个集合来管理 HashMap,并接受某个同事对象消息,完成相应的任务
  • ConcreteColleague 具体的同事类,会有很多,每个同事只知道自己的行为,而不了解其他同事类的行为(方法),但是他们都依赖中介者对象;同事间实现解耦,提高了扩展性

3)案例分析

智能家庭项目

  • 智能家庭包括各种设备,闹钟、咖啡机、电视机、窗帘等
  • 主人要看电视时,各个设备可以协同工作,自动完成看电视的准备工作,比如流程为:
    • 闹铃响起
    • 咖啡机开始做咖啡
    • 窗帘自动落下
    • 电视机开始播放

同事之间(闹钟、咖啡机、电视、窗帘、电话)实现解耦,方便扩展

每个同事都与中介关联,图中只展示 闹钟和中介的关联,其余省略

中介抽象类 Mediator

package mediator.mediator;

import mediator.colleague.Colleague;

/**
 * @author 土味儿
 * Date 2021/7/29
 * @version 1.0
 * 中介抽象类
 */
public abstract class Mediator {
    /**
     * 注册特定同事,放入集合中
     * @param colleagueName
     * @param colleague
     */
    public abstract void register(String colleagueName, Colleague colleague);

    /**
     * 获取特定同事发出的消息
     * @param stateChange
     * @param colleagueName
     */
    public abstract  void getMessage(int stateChange,String colleagueName);

    /**
     * 发送消息
     */
    public abstract void sendMessage();
}

具体中介实现者 ConcreteMediator

package mediator.mediator;

import mediator.colleague.*;

import java.util.HashMap;
import java.util.Map;

/**
 * @author 土味儿
 * Date 2021/7/29
 * @version 1.0
 * 具体中介实现者
 */
public class ConcreteMediator extends Mediator {
    // 集合,放入同事对象
    private Map<String,Colleague> colleagueMap;
    // 集合,存放同事名称
    private HashMap<String, String> interMap;

    /**
     * 构造器
     */
    public ConcreteMediator() {
        this.colleagueMap = new HashMap<String,Colleague>();
        this.interMap = new HashMap<String,String>();
    }

    /**
     * 注册同事对象
     * @param colleagueName
     * @param colleague
     */
    @Override
    public void register(String colleagueName, Colleague colleague) {
        colleagueMap.put(colleagueName,colleague);

        if (colleague instanceof AlarmColleague) {
            interMap.put("Alarm", colleagueName);
        } else if (colleague instanceof CoffeeMachineColleague) {
            interMap.put("CoffeeMachine", colleagueName);
        }

    }

    /**
     * 核心方法
     * 获取消息并处理
     * @param stateChange
     * @param colleagueName
     */
    @Override
    public void getMessage(int stateChange, String colleagueName) {
        // 闹钟
        if(colleagueMap.get(colleagueName) instanceof AlarmColleague){
            if(stateChange == 0 ){// 闹钟响起:开始
                // 开始制作咖啡
                ((CoffeeMachineColleague)(colleagueMap.get(interMap.get("CoffeeMachine")))).startCoffee();
                // 落下窗帘
                // 打开电视
            }else if(stateChange == 1){// 闹钟响起:结束
                // 关闭电视
                // 升级窗帘
            }
        }
    }

    @Override
    public void sendMessage() {

    }
}

抽象同事类 Colleague

package mediator.colleague;

import mediator.mediator.Mediator;

/**
 * @author 土味儿
 * Date 2021/7/29
 * @version 1.0
 * 抽象同事类
 */
public abstract class Colleague {
    // 中介者
    private Mediator mediator;
    // 同事名称
    private String name;

    /**
     * 构造器
     * @param mediator
     * @param name
     */
    public Colleague(Mediator mediator, String name) {
        this.mediator = mediator;
        this.name = name;
    }

    /**
     * 发送消息
     * @param stateChange
     */
    public abstract void sendMessage(int stateChange);

    public String getName() {
        return name;
    }

    public Mediator getMediator() {
        return mediator;
    }
}

具体同事实现类

package mediator.colleague;

import mediator.mediator.Mediator;

/**
 * @author 土味儿
 * Date 2021/7/29
 * @version 1.0
 * 闹钟
 */
public class AlarmColleague extends Colleague {
    /**
     * 构造器
     *
     * @param mediator
     * @param name
     */
    public AlarmColleague(Mediator mediator, String name) {
        super(mediator, name);
        mediator.register(name,this);
    }

    /**
     * 闹钟发声
     * @param stateChange
     */
    public void sendAlarm(int stateChange){
        if(stateChange == 0 ){// 闹钟响起:开始
            System.out.println("闹钟响起开始");
        }else if(stateChange == 1){// 闹钟响起:结束
            System.out.println("闹钟响起结束");
        }
        sendMessage(stateChange);
    }

    /**
     * 发送消息
     * @param stateChange
     */
    @Override
    public void sendMessage(int stateChange) {
        this.getMediator().getMessage(stateChange,this.getName());
    }
}
package mediator.colleague;

import mediator.mediator.Mediator;

/**
 * @author 土味儿
 * Date 2021/7/29
 * @version 1.0
 * 咖啡机
 */
public class CoffeeMachineColleague extends Colleague{
    /**
     * 构造器
     *
     * @param mediator
     * @param name
     */
    public CoffeeMachineColleague(Mediator mediator, String name) {
        super(mediator, name);
        mediator.register(name,this);
    }

    @Override
    public void sendMessage(int stateChange) {
        this.getMediator().getMessage(stateChange,this.getName());
    }

    /**
     * 开始制作咖啡
     */
    public void startCoffee(){
        System.out.println("开始制作咖啡");
    }

    /**
     * 咖啡制作完成
     */
    public void finishCoffee(){
        System.out.println("咖啡制作完成");
    }
}

客户端

package mediator;

import mediator.colleague.*;
import mediator.mediator.*;

/**
 * @author 土味儿
 * Date 2021/7/29
 * @version 1.0
 * 客户端
 */
public class Client {
    public static void main(String[] args) {
        // 创建中介者对象
        Mediator mediator = new ConcreteMediator();
        // 创建闹钟
        AlarmColleague alarmColleague = new AlarmColleague(mediator, "闹钟");
        // 创建咖啡机
        CoffeeMachineColleague coffeeMachineColleague = new CoffeeMachineColleague(mediator, "咖啡机");

        alarmColleague.sendAlarm(0);
        alarmColleague.sendAlarm(1);
    }
}

运行结果

闹钟响起开始
开始制作咖啡
闹钟响起结束

7、备忘录模式

Memento Pattern

1)基本介绍

  • 备忘录模式(Memento Pattern)在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态
  • 可以这样理解备忘录模式:现实生活中的备忘录是用来记录某些要去做的事情,或者是记录已经达成的共同意 见的事情,以防忘记了。而在软件层面,备忘录模式有着相同的含义,备忘录对象主要用来记录一个对象的某 种状态,或者某些数据,当要做回退时,可以从备忘录对象里获取原来的数据进行恢复操作
  • 备忘录模式属于行为型模式

2)原理类图

  • Originator :对象(需要保存状态的对象)
  • Memento:备忘录对象,负责保存记录,即 Originator 内部状态
  • Caretaker:守护者对象,负责保存多个备忘录对象,使用集合管理,提高效率
  • 如果希望保存多个 originator 对象的不同时间的状态,也可以,只需要 HashMap <String,集合>

3)案例分析

游戏角色有攻击力和防御力,在大战 Boss前保存自身的状态(攻击力和防御力),当大战 Boss后攻击力和防御力下降,从备忘录对象恢复到大战前的状态

​ 可以存储多个角色的状态,每个角色有多个状态

备忘录对象 Memento

package memento.originator.more;

/**
 * @author 土味儿
 * Date 2021/7/30
 * @version 1.0
 * 备忘录对象
 */
public class Memento {
    // 攻击力
    private int vit;
    // 防御力
    private int def;

    public Memento(int vit, int def) {
        this.vit = vit;
        this.def = def;
    }

    public int getVit() {
        return vit;
    }

    public int getDef() {
        return def;
    }
}

游戏角色 GameRole

GameRole1、GameRole2、GameRole3

package memento.originator.more.gamerole;

import memento.originator.more.Memento;

/**
 * @author 土味儿
 * Date 2021/7/30
 * @version 1.0
 * 游戏角色1
 */
public class GameRole1 {
    // 角色名称
    private String name;
    // 攻击力
    private int vit;
    // 防御力
    private int def;

    public GameRole1() {
        this.name = "角色1";
        this.vit = 100;
        this.def = 100;
    }

    /**
     * 创建当前状态的备忘录
     *
     * @return
     */
    public Memento createMemento() {
        return new Memento(vit, def);
    }

    /**
     * 从备忘录中恢复状态
     */
    public void recoverFromMemento(Memento memento) {
        this.vit = memento.getVit();
        this.def = memento.getDef();
    }

    /**
     * 显示
     */
    public void display() {
        System.out.println(name + " 攻击力:" + vit + " 防御力:" + def);
    }

    public String getName() {
        return name;
    }

    public void setVit(int vit) {
        this.vit = vit;
    }

    public void setDef(int def) {
        this.def = def;
    }
}

守护者对象 Caretaker

package memento.originator.more;

import java.util.*;

/**
 * @author 土味儿
 * Date 2021/7/30
 * @version 1.0
 * 守护者对象
 * 存储备忘录
 */
public class Caretaker {
    // 存储某个角色备忘录集合
    private List<Memento> mementoList;
    // 存储所有角色的备忘录集合
    private HashMap<String,List<Memento>> mementoMap;

    /**
     * 构造器
     */
    public Caretaker() {
        //this.mementoList = new ArrayList<>();
        this.mementoMap = new HashMap<>();
    }

    /**
     * 添加
     * @param gameRoleName
     * @param memento
     */
    public void add(String gameRoleName,Memento memento){
        // 检查Map中是否存当前角色
        Set<String> keySet = mementoMap.keySet();
        // Map中是否包含当前角色:默认不包含
        boolean include = false;
        for (String k : keySet) {
            if(k.equals(gameRoleName)){
                include = true;
                break;
            }
        }
        // 不存在:直接添加
        if(!include){
            mementoList = new ArrayList<>();
            mementoList.add(memento);
            // HashMap 如果添加相同的key,后面的会替换前面的key-value(key不会替换,value会替换)
            mementoMap.put(gameRoleName,mementoList);
            return;
        }
        // 存在:从Map中取出List,把状态加入List,再把List存入Map
        mementoList = mementoMap.get(gameRoleName);
        mementoList.add(memento);
        // HashMap 如果添加相同的key,后面的会替换前面的key-value(key不会替换,value会替换)
        mementoMap.put(gameRoleName,mementoList);
    }

    /**
     * 获取
     * @param gameRoleName
     * @param index
     * @return
     */
    public Memento get(String gameRoleName,int index){
        return mementoMap.get(gameRoleName).get(index);
    }

    /**
     * 删除
     * @param index
     */
    public void remove(String gameRoleName,int index){
        mementoMap.get(gameRoleName).remove(index);
    }
}

客户端 Client

package memento.originator.more;

import memento.originator.more.gamerole.GameRole1;
import memento.originator.more.gamerole.GameRole2;
import memento.originator.more.gamerole.GameRole3;

/**
 * @author 土味儿
 * Date 2021/7/30
 * @version 1.0
 * 客户端
 */
public class Client {
    public static void main(String[] args) {
        // 创建守护者
        Caretaker caretaker = new Caretaker();

        // 创建游戏角色1
        GameRole1 gameRole1 = new GameRole1();
        // 设置状态
        gameRole1.setVit(80);
        gameRole1.setDef(70);
        caretaker.add(gameRole1.getName(),gameRole1.createMemento());

        // 设置状态
        gameRole1.setVit(60);
        gameRole1.setDef(50);
        caretaker.add(gameRole1.getName(),gameRole1.createMemento());

        // 设置状态
        gameRole1.setVit(50);
        gameRole1.setDef(40);
        caretaker.add(gameRole1.getName(),gameRole1.createMemento());

        gameRole1.display();

        gameRole1.recoverFromMemento(caretaker.get(gameRole1.getName(),1));

        gameRole1.display();

        // 创建游戏角色2
        GameRole2 gameRole2 = new GameRole2();
        // 设置状态
        gameRole2.setVit(82);
        gameRole2.setDef(72);
        caretaker.add(gameRole2.getName(),gameRole2.createMemento());

        // 创建游戏角色3
        GameRole3 gameRole3 = new GameRole3();
        // 设置状态
        gameRole3.setVit(83);
        gameRole3.setDef(73);
        caretaker.add(gameRole3.getName(),gameRole3.createMemento());

        // 设置状态
        gameRole2.setVit(62);
        gameRole2.setDef(52);
        caretaker.add(gameRole2.getName(),gameRole2.createMemento());
        gameRole2.display();

        gameRole2.recoverFromMemento(caretaker.get(gameRole2.getName(),0));
        gameRole2.display();
    }
}

运行结果

角色1 攻击力:50 防御力:40
角色1 攻击力:60 防御力:50
角色2 攻击力:62 防御力:52
角色2 攻击力:82 防御力:72

4)注意事项和细节

  • 给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态

  • 实现了信息的封装,使得用户不需要关心状态的保存细节

  • 如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存,这个需要注意

  • 适用的应用场景:

    • 后悔药
    • 打游戏时的存档
    • Windows里的 ctri + z
    • IE中的后退
    • 数据库的事务管理
  • 为了节约内存,备忘录模式可以和原型模式配合使用

8、解释器模式

Interpreter Pattern

1)基本介绍

  • 在编译原理中,一个算术表达式通过词法分析器形成词法单元,而后这些词法单元再通过语法分析器构建语法分析树,最终形成一颗抽象的语法分析树。这里的词法分析器和语法分析器都可以看做是解释器
  • 解释器模式(Interpreter Pattern):是指给定一个语言(表达式),定义它的文法的一种表示,并定义一个解释器,使用该解释器来解释语言中的句子(表达式)
  • 应用场景
    • 编译器
    • 运算表达式计算
    • 正则表达式
    • 机器人等

2)原理类图

  • Context:是环境角色,含有解释器之外的全局信息
  • AbstractExpression:抽象表达式,声明一个抽象的解释操作,这个方法为抽象语法树中所有的节点所共享
  • TerminalExpression:为终结符表达式,实现与文法中的终结符相关的解释操作
  • NonTermialExpression:为非终结符表达式,为文法中的非终结符实现解释操作
  • 通过 Client 输入 Context 和 TerminalExpression 信息

3)案例分析

通过解释器模式来实现加减运算, 如计算 a+b-c 的值

  • Expression 抽象表达式(a+b-c)

    • VarExpression 变量表达式(a、b、c)
    • SymbolExpression 运算符表达式(+、-)
      • AddExpression 加法表达式
      • SubExpression 减法表达式
  • Calculator 计算器

4)Spring中的应用

Spring框架中 SpelExpressionParser 就使用到解释器模式

5)注意事项和细节

  • 当有一个语言需要解释执行,可将该语言中的句子表示为一个抽象语法树,就可以考虑使用解释器模式,让程 序具有良好的扩展性
  • 可能带来的问题:会引起类膨胀,解释器模式采用递归调用方法,将会导致调试非常复杂、效率可能降低

9、状态模式

State Pattern

1)基本介绍

  • 状态模式(State Pattern):它主要用来解决对象在多种状态转换时,需要对外输出不同的行为的问题。状态和行为是一一对应的,状态之间可以相互转换
  • 当一个对象的内在状态改变时,允许改变其行为,这个对象看起来像是改变了其类

2)原理类图

  • Context 类为环境角色,用于维护 State 实例,这个实例定义当前状态
  • State 是抽象状态角色,定义一个接口封装与 Context 的一个特定接口相关行为
  • ConcreteState 具体的状态角色,每个子类实现一个与 Context 的一个状态相关行为

3)抽奖案例

APP抽奖活动

具体要求如下:

  • 假如每参加一次这个活动要扣除用户 50 积分,中奖概率是 10%
  • 奖品数量固定,抽完就不能抽奖
  • 活动有四个状态:可以抽奖、待抽奖、发放奖品和奖品领完
  • 状态转换关系图

抽奖状态接口 RaffleState

package state.raffle;

/**
 * @author 土味儿
 * Date 2021/7/30
 * @version 1.0
 * 抽奖状态接口
 */
public interface RaffleState {
    /**
     * 扣积分
     */
    void deductIntegral();

    /**
     * 抽奖
     */
    boolean raffle();

    /**
     * 发奖品
     */
    void dispensePrize();
}

具体状态实现类

package state.raffle.state;

import state.raffle.RaffleActivity;
import state.raffle.RaffleState;

/**
 * @author 土味儿
 * Date 2021/7/30
 * @version 1.0
 * 待抽奖状态
 */
public class WaitRaffleState implements RaffleState {
    // 抽奖活动
    private RaffleActivity raffleActivity;

    /**
     * 构造器
     * @param raffleActivity
     */
    public WaitRaffleState(RaffleActivity raffleActivity) {
        this.raffleActivity = raffleActivity;
    }

    /**
     * 扣积分
     * 只有 待抽奖状态 可以扣积分,扣除后将状态设置成 可抽奖状态
     */
    @Override
    public void deductIntegral() {
        System.out.println("扣除 50 积分成功!您可以抽奖了!");
        // 把状态设置为 可抽奖状态
        raffleActivity.setState(raffleActivity.getCanRaffleState());
    }

    /**
     * 抽奖
     * 待抽奖状态 不能抽奖
     * @return
     */
    @Override
    public boolean raffle() {
        System.out.println("扣除积分后才可以抽奖哟");
        return false;
    }

    /**
     * 发奖品
     */
    @Override
    public void dispensePrize() {
        System.out.println("待抽奖状态不能发放奖品哟");
    }
}
package state.raffle.state;

import state.raffle.RaffleActivity;
import state.raffle.RaffleState;

import java.util.Random;

/**
 * @author 土味儿
 * Date 2021/7/30
 * @version 1.0
 * 可抽奖状态
 */
public class CanRaffleState implements RaffleState {
    // 抽奖活动
    private RaffleActivity raffleActivity;

    /**
     * 构造器
     *
     * @param raffleActivity
     */
    public CanRaffleState(RaffleActivity raffleActivity) {
        this.raffleActivity = raffleActivity;
    }

    /**
     * 扣积分
     */
    @Override
    public void deductIntegral() {
        System.out.println("已经扣过积分了,请抽奖!");
    }

    /**
     * 抽奖
     *
     * @return
     */
    @Override
    public boolean raffle() {
        System.out.println("正在抽奖,请稍候...");
        // 随机抽奖:中奖概率30%
        int i = new Random().nextInt(100);
        // 中奖了
        if (i < 30) {
            System.out.println("㳟喜您!中奖了...");
            // 把状态设置为 发放奖品状态
            raffleActivity.setState(raffleActivity.getDispensePrizeState());
            return true;
        }
        System.out.println("很遗憾没有中奖!");
        // 把状态设置为 待抽奖状态
        raffleActivity.setState(raffleActivity.getWaitRaffleState());
        return false;
    }

    /**
     * 发放奖品
     */
    @Override
    public void dispensePrize() {
        System.out.println("中奖后才可以发放奖品!");
    }
}
package state.raffle.state;

import state.raffle.RaffleActivity;
import state.raffle.RaffleState;

/**
 * @author 土味儿
 * Date 2021/7/30
 * @version 1.0
 * 发放奖品状态
 */
public class DispensePrizeState implements RaffleState {
    // 抽奖活动
    private RaffleActivity raffleActivity;

    /**
     * 构造器
     * @param raffleActivity
     */
    public DispensePrizeState(RaffleActivity raffleActivity) {
        this.raffleActivity = raffleActivity;
    }

    /**
     * 扣积分
     */
    @Override
    public void deductIntegral() {
        System.out.println("发放奖品状态不扣积分!");
    }

    /**
     * 抽奖
     * @return
     */
    @Override
    public boolean raffle() {
        System.out.println("发放奖品状态不能抽奖");
        return false;
    }

    /**
     * 发放奖品
     * 根据奖品数量,判断状态
     */
    @Override
    public void dispensePrize() {
        if(raffleActivity.getCount() > 0){
            System.out.println("请领奖....");
            // 奖品数量减1
            raffleActivity.setCount(raffleActivity.getCount()-1);
            // 判断最新奖品数量,然后设置状态
            if(raffleActivity.getCount() > 0){
                // 把状态设置为 待抽奖状态
                raffleActivity.setState(raffleActivity.getWaitRaffleState());
                return;
            }
            // 把状态设置为 奖品发完状态
            raffleActivity.setState(raffleActivity.getPrizeOverState());
            return;
        }
        System.out.println("没有奖品了...");
        // 把状态设置为 奖品发完状态
        raffleActivity.setState(raffleActivity.getPrizeOverState());
    }
}
package state.raffle.state;

import state.raffle.RaffleActivity;
import state.raffle.RaffleState;

/**
 * @author 土味儿
 * Date 2021/7/30
 * @version 1.0
 * 奖品发完状态
 */
public class PrizeOverState implements RaffleState {
    // 抽奖活动
    private RaffleActivity raffleActivity;

    /**
     * 构造器
     * @param raffleActivity
     */
    public PrizeOverState(RaffleActivity raffleActivity) {
        this.raffleActivity = raffleActivity;
    }
    @Override
    public void deductIntegral() {
        System.out.println("奖品发完了!不扣积分");
    }

    @Override
    public boolean raffle() {
        System.out.println("奖品发完了!不能抽奖");
        return false;
    }

    @Override
    public void dispensePrize() {
        System.out.println("奖品发完了!");
    }
}

抽奖活动类 RaffleActivity

package state.raffle;

import state.raffle.state.CanRaffleState;
import state.raffle.state.DispensePrizeState;
import state.raffle.state.PrizeOverState;
import state.raffle.state.WaitRaffleState;

/**
 * @author 土味儿
 * Date 2021/7/30
 * @version 1.0
 * 抽奖活动
 */
public class RaffleActivity {
    // 当前状态
    private RaffleState state = null;
    // 四种状态
    private WaitRaffleState waitRaffleState;
    private CanRaffleState canRaffleState;
    private DispensePrizeState dispensePrizeState;
    private PrizeOverState prizeOverState;
    // 奖品数量
    private int count = 0;

    /**
     * 构造器
     *
     * @param count
     */
    public RaffleActivity(int count) {
        this.waitRaffleState = new WaitRaffleState(this);
        this.canRaffleState = new CanRaffleState(this);
        this.dispensePrizeState = new DispensePrizeState(this);
        this.prizeOverState = new PrizeOverState(this);

        this.state = waitRaffleState;
        this.count = count;
    }

    /**
     * 扣积分
     */
    public void deductIntegral() {
        state.deductIntegral();
    }

    /**
     * 抽奖
     */
    public void raffle() {
        if (state.raffle()) {
            // 抽奖成功,发放奖品
            //setCount(getCount()-1);
            state.dispensePrize();
        }
    }

    public void setState(RaffleState state) {
        this.state = state;
    }

    public WaitRaffleState getWaitRaffleState() {
        return waitRaffleState;
    }

    public CanRaffleState getCanRaffleState() {
        return canRaffleState;
    }

    public DispensePrizeState getDispensePrizeState() {
        return dispensePrizeState;
    }

    public PrizeOverState getPrizeOverState() {
        return prizeOverState;
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }
}

调用客户端 Client

package state.raffle;

/**
 * @author 土味儿
 * Date 2021/7/30
 * @version 1.0
 * 客户端
 */
public class Client {
    public static void main(String[] args) {
        // 创建抽奖活动:奖品数 2
        RaffleActivity raffleActivity = new RaffleActivity(2);

        // 循环抽奖,如果没有奖品就退出
        int i = 0;
        while(raffleActivity.getCount() > 0){
            System.out.println("\n===== 第" + ++i + "次抽奖 (剩余奖品数:" + raffleActivity.getCount() + ") =====");
            // 扣积分
            raffleActivity.deductIntegral();
            // 抽奖
            raffleActivity.raffle();
        }

/*        // 循环抽奖30次,即使没有奖品了,仍然抽奖
        for (int i = 1; i < 31; i++) {
           System.out.println("\n===== 第" + i + "次抽奖 (剩余奖品数:" + raffleActivity.getCount() + ") =====");
            // 扣积分
            raffleActivity.deductIntegral();
            // 抽奖
            raffleActivity.raffle();
        }*/

    }
}

运行结果

===== 第1次抽奖 (剩余奖品数:2) =====
扣除 50 积分成功!您可以抽奖了!
正在抽奖,请稍候...
很遗憾没有中奖!

===== 第2次抽奖 (剩余奖品数:2) =====
扣除 50 积分成功!您可以抽奖了!
正在抽奖,请稍候...
㳟喜您!中奖了...
请领奖....

===== 第3次抽奖 (剩余奖品数:1) =====
扣除 50 积分成功!您可以抽奖了!
正在抽奖,请稍候...
很遗憾没有中奖!

===== 第4次抽奖 (剩余奖品数:1) =====
扣除 50 积分成功!您可以抽奖了!
正在抽奖,请稍候...
㳟喜您!中奖了...
请领奖....

4)借贷平台案例

  • 借贷平台的订单,有审核-发布-完结等等步骤,随着操作的不同,会改变订单的状态,项目中的这个模块实 现就会使用到状态模式
  • 通常通过 if/else 判断订单的状态,从而实现不同的逻辑,伪代码如下

5)注意事项和细节

  • 代码有很强的可读性:状态模式将每个状态的行为封装到对应的一个类中

  • 维护方便:将容易产生问题的 if-else 语句删除了,如果把每个状态的行为都放到一个类中,每次调用方法时都要判断当前是什么状态,不但会产出很多 if-else 语句,而且容易出错

  • 符合 OCP开闭原则:容易增删状态

  • 缺点:会产生很多类:每个状态都要一个对应的类,当状态过多时会产生很多类,加大维护难度

  • 应用场景:当一个事件或者对象有很多种状态,状态之间会相互转换,对不同的状态要求有不同的行为的时候, 可以考虑使用状态模式

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

土味儿~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值