2021-11-15

设计模式:策略模式和状态模式对比


前言

在设计模式中,有很多类似的设计模式。比如之前设计的适配器模式和代理模式,今天我们要分析的策略模式和状态模式也是十分类似的设计模式。


提示:以下是本篇文章正文内容,下面案例可供参考

一、策略模式

策略模式属于对象的行为模式。策略模式中定义算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户端。
我们分析一下策略模式的图解:
在这里插入图片描述
框架代码如下:

public class C02_Strategy {
    public static void main(String[] args) {
        Strategy strategy = new ConcreteStrategyB() ;
        Context context = new Context(strategy) ;
        context.userMethod();
    }
}
/** 环境角色类 */
class Context {
    //持有一个具体策略的对象
    private Strategy strategy;
    /**
     * 构造函数,传入一个具体策略对象
     * @param strategy    具体策略对象
     */
    public Context(Strategy strategy){
        this.strategy = strategy;
    }
    public void userMethod (){
        this.strategy.strategyMethod();
    }
}
/** 抽象策略类 */
interface Strategy {
    // 策略方法
    void strategyMethod () ;
}
/** 具体策略类 */
class ConcreteStrategyA implements Strategy {
    @Override
    public void strategyMethod() {
        System.out.println("策略A方法");
    }
}
class ConcreteStrategyB implements Strategy {
    @Override
    public void strategyMethod() {
        System.out.println("策略B方法");
    }
}

示例:
每年双十一,各大电商平台会推出不同的满减策略,当用户的消费金额满一定额度后,会进行减去一定的优惠额度,从而来一波清仓甩卖,使用策略模式来描述该流程。

public class C01_InScene {
    public static void main(String[] args) {
        // 选择满减策略,走相应的计算方式
        FullReduce strategy = new Full100 ();
        Payment price = new Payment(strategy);
        double quote = price.payment(300);
        System.out.println("最终价格为:" + quote);
    }
}
/**
 * 付款
 */
class Payment {
    private FullReduce fullReduce ;
    public Payment (FullReduce fullReduce){
        this.fullReduce = fullReduce ;
    }
    public double payment (double totalPrice){
        return this.fullReduce.getPayMoney(totalPrice) ;
    }
}
/**
 * 金额满减接口
 */
interface FullReduce {
    double getPayMoney (double totalPrice) ;
}
/**
 * 不同的满减策略
 */
class Full100 implements FullReduce {
    @Override
    public double getPayMoney(double totalPrice) {
        if (totalPrice >= 100){
            totalPrice = totalPrice-20.0 ;
        }
        return totalPrice ;
    }
}
class Full500 implements FullReduce {
    @Override
    public double getPayMoney(double totalPrice) {
        if (totalPrice >= 500){
            totalPrice = totalPrice-120.0 ;
        }
        return totalPrice ;
    }
}

上面可以看出策略模式的关键是:变化的与不变分离,体现了“对修改关闭,对扩展开放”原则。客户端增加行为不用修改原有代码,只要添加一种策略即可,易于切换、易于理解、易于扩展。策略过多是会导致类数目庞大,变得难以维护。
策略模式将变化的部分抽离出来,组合进类中,根据不同的子类,可以"set"不同的行为子类进行,实现动态改变行为。

二、状态模式

状态模式是对象的行为模式,状态模式允许一个对象在其内部状态改变的时候改变其行为。状态模式把对象的行为封装在不同状态的对象中,每一个状态对象都是抽象状态类的子类。意图是让一个对象在其内部状态改变的时候,其行为也随之改变。
在这里插入图片描述
环境角色持有具体状态类的对象实例。这个具体状态类的实例给出此环境对象的现有状态。抽象状态角色,定义一个接口,封装环境对象的状态所对应的行为。具体状态角色,具体状态类实现了环境的状态所对应的行为。

框架代码如下:

public class C02_State {
    public static void main(String[] args){
        Context context = new Context();
        State state = new ConcreteStateA() ;
        context.setState(state);
        context.printInfo("当前环境状态A");
        state = new ConcreteStateB();
        context.setState(state);
        context.printInfo("当前环境状态B");
    }
}
/**
 * 环境角色
 */
class Context {
    private State state;
    public void setState(State state) {
        this.state = state;
    }
    public void printInfo (String info) {
        state.stateInfo(info);
    }
}
/**
 * 抽象状态角色
 */
interface State {
    void stateInfo (String param);
}
/**
 * 具体状态角色
 */
class ConcreteStateA implements State {
    @Override
    public void stateInfo (String info) {
        System.out.println("ConcreteStateA:" + info);
    }
}
class ConcreteStateB implements State {
    @Override
    public void stateInfo (String info) {
        System.out.println("ConcreteStateB:" + info);
    }
}

示例:

public class C01_InScene {
    public static void main(String[] args) {
        Chameleon chameleon = new Chameleon("红色","花丛环境") ;
        LifeContext lifeContext = new LifeContext() ;
        // 树叶环境
        BodyColor bodyColor = new GreenColor ();
        lifeContext.setBodyColor(bodyColor);
        lifeContext.change(chameleon);
        // 树枝环境
        bodyColor = new GrayColor() ;
        lifeContext.setBodyColor(bodyColor);
        lifeContext.change(chameleon);
    }
}
/**
 * 变色龙
 */
class Chameleon {
    public String color ;
    public String contextDesc ;
    public Chameleon(String color, String contextDesc) {
        this.color = color;
        this.contextDesc = contextDesc;
    }
}
/**
 * 变色龙生存环境
 */
class LifeContext {
    private BodyColor bodyColor;
    public void setBodyColor(BodyColor bodyColor) {
        this.bodyColor = bodyColor;
    }
    public void change (Chameleon chameleon){
        bodyColor.change(chameleon) ;
    }
}
/**
 * 变色龙身体颜色抽象类
 */
interface BodyColor {
    void change (Chameleon chameleon);
}
/**
 * 变色龙身体颜色具体类
 */
class GreenColor implements BodyColor {
    @Override
    public void change(Chameleon chameleon) {
        System.out.pr

状态模式将容易产生问题的if-else语句拆分,状态模式将每个状态的行为封装到对应的一个类中,代码有很强的可读性。而且状态模式符合“开闭原则”,容易增删操作,管理状态。当存在很多状态时。每个状态都要一个对应的类,会产生很多类,增加维护难度。

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


总结

策略模式封装了一组相关算法,它允许Client在运行时使用可互换的行为;状态模式帮助一个类在不同的状态显示不同的行为。状态模式封装了对象的状态,而策略模式封装算法或策略。因为状态是跟对象密切相关的,它不能被重用;而通过从Context中分离出策略或算法,我们可以重用它们。
在状态模式中,每个状态通过持有Context的引用,来实现状态转移;但是每个策略都不持有Context的引用,它们只是被Context使用。策略实现可以作为参数传递给使用它的对象,例如Collections.sort(),它的参数包含一个Comparator策略。另一方面,状态是Context对象自己的一部分,随着时间的推移,Context对象从一个状态转移到另一个状态。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值