本文中知识点概述:
- 策略模式和状态模式的基本概念
- 策略模式和状态模式的区别
- 策略模式和状态模式在实际场景的使用
1.策略模式和状态模式的基本概念
策略模式 定义一系列的算法,并将每一个算法封装起来,而且使他们可以相互替换,策略模式让算法独立于使用它的客户而独立变化.
状态模式 当一个对象的内在状态改变时允许改变其行为,这个对象开起来像是改变了其类.
2.策略模式和状态模式的区别
开始的时候我一直对这两个设计模式分不清楚,为什么这么说呢?因为两种设计模式都有相应的选择状态,但是只要你记住一个主要的区别就能很好的区分相应的设计模式,状态模式封装的是内在的行为,但是用户是不知道的(这里最经典的例子就是关于登陆的问题,后面会讲),而策略模式封装的是一系列的算法,是可以给用户进行选择的.
其实两种设计模式可以说是亲兄弟,基本上的实现都是差不多的.
- 策略模式: 封装的是一些列的算法供用户自行选择,主要是针对一系列算法而言,用户可以自行选择.
- 状态模式: 封装的是内部的运行状态,但是对外而言都是看不见的
3.策略模式和状态模式在实际中的使用场景
3.1策略模式的使用场景
- 针对同一类型问题的多种处理方式,仅仅是具体行为有差别时;
- 需要安全地封装多种同一类型的操作;
- 出现同一抽象类有多个子类,而有需要使用if-else或者switch-case来选择具体子类时
这里举个例子吧!让大家好好理解一下:
我们平时都喜欢出去玩,我在北京出去的时候都会查询地图,然后相应的会出来好多路线让我去选择,其实这里就时一个相应的路线策略,你可以坐地铁或者公交车去.这个就是相应的用户选择,他们只是提供相应的策略,至于用户怎么去选择我们不管...下面看一下具体的代码实现吧!
- 首先先创建一个路线的目的地接口
public interface TravelRoute {
/**
* author : 贺金龙
* create time : 2017/12/23 18:35
* description : 目的地的方法
*/
void destination();
}
首先这个类的作用是提供一个目的地的基类,主要使为了后面多态的使用做准备.因为这里的策略使通过用户进行设置的,这里设置一个相应的类的话,接口比较好,其实你写个抽象类也是可以的,看你习惯了!
- 地铁的实现类(可提供选择的实现类,也就是其中一种选择)
public class Subway implements TravelRoute {
@Override
public void destination() {
System.out.println("相应的地铁出行");
}
}
- 公交出行的实现类(可提供的另一种实现类,也是其中一种选择)
public class Bus implements TravelRoute {
@Override
public void destination() {
System.out.println("相应的公交出行");
}
}
- 相应的控制类(这里也是通过这个类进行相应的策略的)
public class TravelRouteSelect implements TravelRoute{
private TravelRoute mRoute;
public TravelRouteSelect() {
}
public void setTeavelRouteStatus(TravelRoute travelRoute){
this.mRoute = travelRoute;
}
@Override
public void destination() {
/*具体的出行方式*/
mRoute.destination();
}
}
- 具体的调用
public static void main(String[] args) {
TravelRouteSelect select = new TravelRouteSelect();
select.setTeavelRouteStatus(new Subway());//这里选择了相应的地铁出行
select.destination();
}
- 相应的输出
相应的地铁出行
上面就是一个策略模式的简单实现,其实主要是相应控制类中提供的一个相应的设置的方法,这个是最主要的地方, 这里通过设置相应的策略,出行的方式也发生了相应的改变.
注意的地方
- 首先setTeavelRouteStatus(TravelRoute travelRoute)方法你要是不调用的话,会出项空指针异常的情况,开始的时候我也没有注意到这个问题,但是后来想到之后,这里可能程序上会给用户一个相应的选择,防止用户不选择出现空的情况,其实很简单,只要在相应控制类创建TravelRoute travelRoute的时候直接对应一个对象就可以了.这样即便是你不选择相应的出行方式也会默认有一个出行方式的.
- 其实可以不适用接口去创建基类的,比如说你有要子类有一些公共的方法,那么这里你可以把相应的方法提出来,用一个抽象类去实现就好了.
3.2状态模式的使用场景
- 一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为;
- 代码中包含大量于对象状态有关的条件语句;
- 状态模式将每一个条件分支放在一个独立的类中,这似的你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立存在,这样通过多来去除过错的重复的if-else等分支语句
这里举一个项目中实际的例子说明一下:
在项目中但凡有游客模式的情况下,都会涉及到点击相应的按钮要判断相应的登陆逻辑,如果没有登陆的话,去登陆操作,如果登陆的话去到指定的页面!一般的app都是这种逻辑,但是实现的方式就千差万别了.开始的时候我也是各种if-else的判断.
- 登陆状态的接口(主要是提供相应的未登录和登陆的相应的实现)
public interface LoginSelect {
/**
* author : 贺金龙
* create time : 2017/12/23 19:20
* description : 相应状态的实现
*/
void loginSelect();
}
- 相应的登陆的状态
public class LoginStatus implements LoginSelect {
@Override
public void loginSelect() {
System.out.println("已经登陆了,去下一个页面");
}
}
- 相应的未登录的状态
public class NoLoginStatus implements LoginSelect {
@Override
public void loginSelect() {
System.out.println("没有进行登陆,跳转到登陆页面");
}
}
- 相应的控制类
public class LoginControl implements LoginSelect {
private LoginSelect mLoginSelect;
public LoginControl() {
}
@Override
public void loginSelect() {
if (自己项目判断登陆的方法) {
setStatus(new LoginStatus());
} else {
setStatus(new NoLoginStatus());
}
mLoginSelect.loginSelect();
}
private void setStatus(LoginSelect status) {
mLoginSelect = status;
}
}
- 相应的调用
public static void main(String[] args) {
LoginControl control = new LoginControl();
control.loginSelect();
}
上面就是一个相应的状态模式的实现,这里其实你可以设置多种状态,有的人可能说你写了这么多代码就实现一个这么简单的逻辑,是不是有点小题大作了,其实不然,你想这么一个问题,比如说你们的项目中有这种操作,但是有一天产品跑来加了一种状态,你怎么办,跑到相应的代码的地方是一顿加啊,别问我为什么,因为以前的我干过这么一个事情,别提有多难受了....
其实策略模式和状态模式实现方法都是类似的,在我的理解中,只是两种模式作用不同,其实写法上都差不多,策略模式主要封装的是相应的算法,供用户自行去选择.而状态模式封装的是行为,其实这种行为对于用户来说,可能不知道,但是代码里面已经做了相应的处理了.
写的不好的地方还请大家见谅,有什么问题或者是不对的地方,请及时指出,马上更正