Java--设计模式(策略和状态)

策略模式概念
# 定义
运行时更改类的行为或算法,从而达到修改其功能的目的;
# 使用场景
一个系统需要动态地在几种算法中选择一种,而这些算法之间仅仅是他们的行为不同。
此外决策过程中过多的出现if else,也可以考虑使用该模式。
# 实现
将这些算法封装成可单独运行的类,由使用者根据需要进行替换。
# 优点
较为灵活,扩展性好,避免大量的if else结构。
# 缺点
对外暴露了类所有的行为和算法,行为过多导致策略类膨胀。
状态模式概念
# 定义
运行时类的行为由其状态决定;
# 使用场景: 
对象依赖装填,行为随状态改变而改变的情景,或者存在大量的if else和分支结构等;
# 实现:
将对象的状态封装成单个的类,每个状态处理该状态下的事务,并控制该状态到其他状态的转移;
# 优点: 
容易新加状态,封装了状态转移规则,每个状态可以被复用和共享,避免大量的if else结构。
# 缺点: 
该模式结构和实现相对复杂,状态过多导致增加类和对象个数。
同时由于由每个状态控制向其他状态的转移,新加状态必须要修改现有的部分状态才能加入状态机中生效。
策略和状态模式的同异
# 相同点
两者通过将行为和状态拆分成一系列小的组件,由条件和状态进行功能更替,这样符合开闭原则,便于扩展。
此外均可作为if else或者分支的替换方案;支持的最大行为和状态均有限;
# 不同点
策略模式中,类的功能是根据当前条件主动更改;
状态模式中,类的功能是被动由当前状态更改;
策略模式中每个行为或算法之间没有关联;
状态模式中的状态之间有关联,并且状态本身控制着状态转移;
策略模式原理
# Context:
使用了某种策略的类,其行为由其包含的具体的策略决定,该类能主动修改使用的策略从而改变其行为;
# Strategy:
抽象策略类,用于定义所有支持的算法公共接口;
# ConcreteStrategy:
能够被Context使用的具体的策略;

在这里插入图片描述

状态模式原理
# Context:
带有某个状态标记的类,其行为由其当前的状态决定,类状态的转移由状态来控制;
# State:
抽象状态类,用于定义Context所有状态的公共接口;
# ConcreteState:
Context类的某种具体状态,包含了该状态下处理的事务并控制向他状态转移;

在这里插入图片描述

实例——策略模式

在这里插入图片描述

// 抽象策略接口:Compression
public interface Compression {
    void doCompression();
}

// 快速压缩算法:Rapid
public class Rapid implements Compression {
    @Override
    public void doCompression() {
        System.out.println("Use rapid compression strategy!");
    }
}

// 高效压缩算法:Efficient
public class Efficient implements Compression {
    @Override
    public void doCompression() {
        System.out.println("Use efficient compression strategy!");
    }
}

// 加密压缩算法:Encrypt
public class Encrypt implements Compression {
    @Override
    public void doCompression() {
        System.out.println("Use encrypt compression strategy!");
    }
}

// 集成上面压缩算法的软件:WinRAR
public class WinRAR {
    private Compression compression = null;
    public WinRAR(Compression compression) {
        this.compression = compression;
    }
    public void setStrategy(Compression compression) {
        this.compression = compression;
    }
    public void compression() {
        if (compression != null) {
            compression.doCompression();
        }
    }
}

// 演示:
public class Demo {
    public static void main(String[] args) {
        WinRAR winrar = new WinRAR(new Rapid());
        winrar.compression();
        winrar.setStrategy(new Efficient());
        winrar.compression();
        winrar.setStrategy(new Encrypt());
        winrar.compression();
    }
}

// 结果:
Use rapid compression strategy!
Use efficient compression strategy!
Use encrypt compression strategy!
实例——状态模式
我们通过自动洗衣机工作过程来描述一下状态模式使用。
简单起见,这里我们仅仅考虑【开始】-> 【工作】-> 【结束】,这三个状态。
下面先来看一下其UML的类图:

在这里插入图片描述

// 洗衣机类:Washing
public class Washing {
    private State state = null;
    public void setState(State state) {
        this.state = state;
        if (state == null) {
            System.out.println("Current state: null!");
        } else {
            System.out.println("Current state: " + state.getClass().getName());
        }
    }
    public void request() {
        if (state != null) {
            state.doJob(this);
        }
    }
}

// 抽象状态接口:State
public interface State {
    void doJob(Washing washing);
}

//开始状态:Start
public class Start implements State {
    @Override
    public void doJob(Washing washing) {
        System.out.println("Start Washing Clothes!");
        washing.setState(new Work());
        washing.request();
    }
}

// 工作状态:Work
public class Work implements State{
    @Override
    public void doJob(Washing washing) {
        System.out.println("Working Now!");
        washing.setState(new End());
        washing.request();
    }
}

// 结束状态:End
public class End implements State{
    @Override
    public void doJob(Washing washing) {
        System.out.println("All Finished!");
        washing.setState(null);
    }
}



// 演示:
public class Demo {
    public static void main(String[] args) {
        Washing washing = new Washing();
        washing.setState(new Start());
        washing.request();
    }
}

// 结果:
Current state: state.Start
Start Washing Clothes!
Current state: state.Work
Working Now!
Current state: state.End
All Finished!
Current state: null!
总结(仅限参数)
# 策略模式:
a)频繁使用if else 可能严重消耗性能
策略模式比较适用于,行为类经常在某一个模式下工作,而不是会根据随机条件进行切换。
举个例子,在APP开发过程中,某一功能会依赖于横竖屏状态,那么我们是否需要在每一帧都是使用if else进行判断当前是横屏还是竖屏,然后进行下一步的处理?
显然这会严重消耗性能,正确的做法是将横竖屏处理拆分成两个策略,每次屏幕切换的时候,主动的切一下使用的模式;
b) 并不是所有的if else 和 分支都可以使用策略模式来替代
对于上面的压缩软件的例子,用户会选用一种模式,然后进行下面的工作,这个没问题。
但是如果我们提供的是一个压缩命令,该命令可以根据传递的参数,使用不同的压缩方式,那么使用if else就是必要的,因为我们不知道用户会输入什么参数,使用什么模式。
c) 策略模式没有策略
策略模式的核心是将一系列的操作拆分成可若干可单独重复使用的轮子,特定条件下直接选取其中一个使用,而不是传递条件,使用if else来进行条件判断以执行相应的操作。
从这个角度来看,策略模式名不副实,其不仅没有智能,合理的根据当前条件进行决策,还需要使用者主动的选取一种策略进行执行。这样做有好处,但同时其也变得更加没有策略。
实际开发过程中,我们都希望对方提供的接口简单好用,最好一个接口能搞定所有的问题,因为对于调用者而言,我并不关心你的实现,我只关心简单使用这个接口完成我的需求。
根本原因在于其破坏了封装性,暴露了具体的策略,这是其拆分组件便于扩展的同时带来的一个不可回避的问题,策略模式将决策由执行者提前到了调用者,代码灵活可扩展的同时带来的是使用的不便。
如果说策略模式主要是为了避免大量的if else决策,那么语言支持的话完全可以使用hashtable,分别以条件和函数对象作为key,value来直接根据条件选取对应的操作。对于大量分支尤其适用。
因此实际开发过程中需要根据自己的实际情况权衡利弊。

# 状态模式:
状态模式的核心是将对象每一个状态做的事情分别交给每一个单独的状态对象处理,并且由状态自己控制向其他状态的转移;行为类仅向外提供方便用户使用的接口;
对扩展状态不是特别友好,需要修改其他状态的转移。其次其实现比较灵活,用不好容易出错。

# 小结:
策略模式是通过 Context 本身的决策来主动更替使用的strategy对象达到改变行为的目的,状态模式通过状态转移来被动的更改当前的State对象,状态的改变发生在运行时。
策略模式提前封装一组可以互相替代的算法族,根据需要动态的选择合适的一个来处理问题,而状态模式处理不同状态下, Context 对象行为不同的问题;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

你默然

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

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

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

打赏作者

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

抵扣说明:

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

余额充值