策略模式和状态模式

不怕跌倒,所以飞翔

本文中知识点概述:

  1. 策略模式和状态模式的基本概念
  2. 策略模式和状态模式的区别
  3. 策略模式和状态模式在实际场景的使用

1.策略模式和状态模式的基本概念

  • 策略模式 定义一系列的算法,并将每一个算法封装起来,而且使他们可以相互替换,策略模式让算法独立于使用它的客户而独立变化.

  • 状态模式 当一个对象的内在状态改变时允许改变其行为,这个对象开起来像是改变了其类.

2.策略模式和状态模式的区别

开始的时候我一直对这两个设计模式分不清楚,为什么这么说呢?因为两种设计模式都有相应的选择状态,但是只要你记住一个主要的区别就能很好的区分相应的设计模式,状态模式封装的是内在的行为,但是用户是不知道的(这里最经典的例子就是关于登陆的问题,后面会讲),而策略模式封装的是一系列的算法,是可以给用户进行选择的.
其实两种设计模式可以说是亲兄弟,基本上的实现都是差不多的.

  • 策略模式: 封装的是一些列的算法供用户自行选择,主要是针对一系列算法而言,用户可以自行选择.
  • 状态模式: 封装的是内部的运行状态,但是对外而言都是看不见的

3.策略模式和状态模式在实际中的使用场景

3.1策略模式的使用场景

  • 针对同一类型问题的多种处理方式,仅仅是具体行为有差别时;
  • 需要安全地封装多种同一类型的操作;
  • 出现同一抽象类有多个子类,而有需要使用if-else或者switch-case来选择具体子类时

这里举个例子吧!让大家好好理解一下:

我们平时都喜欢出去玩,我在北京出去的时候都会查询地图,然后相应的会出来好多路线让我去选择,其实这里就时一个相应的路线策略,你可以坐地铁或者公交车去.这个就是相应的用户选择,他们只是提供相应的策略,至于用户怎么去选择我们不管...下面看一下具体的代码实现吧!

  1. 首先先创建一个路线的目的地接口
public interface TravelRoute {

    /**
     * author :  贺金龙
     * create time : 2017/12/23 18:35
     * description : 目的地的方法
     */
    void destination();
}

首先这个类的作用是提供一个目的地的基类,主要使为了后面多态的使用做准备.因为这里的策略使通过用户进行设置的,这里设置一个相应的类的话,接口比较好,其实你写个抽象类也是可以的,看你习惯了!

  1. 地铁的实现类(可提供选择的实现类,也就是其中一种选择)
public class Subway implements TravelRoute {
    @Override
    public void destination() {
        System.out.println("相应的地铁出行");
    }
}
  1. 公交出行的实现类(可提供的另一种实现类,也是其中一种选择)
public class Bus implements TravelRoute {
    @Override
    public void destination() {
        System.out.println("相应的公交出行");
    }
}
  1. 相应的控制类(这里也是通过这个类进行相应的策略的)
public class TravelRouteSelect implements TravelRoute{

    private TravelRoute mRoute;

    public TravelRouteSelect() {
    }

    public void setTeavelRouteStatus(TravelRoute travelRoute){
        this.mRoute = travelRoute;
    }

    @Override
    public void destination() {
        /*具体的出行方式*/
        mRoute.destination();
    }
}
  1. 具体的调用
    public static void main(String[] args) {
        TravelRouteSelect select = new TravelRouteSelect();
        select.setTeavelRouteStatus(new Subway());//这里选择了相应的地铁出行
        select.destination();
    }
  1. 相应的输出
相应的地铁出行

上面就是一个策略模式的简单实现,其实主要是相应控制类中提供的一个相应的设置的方法,这个是最主要的地方, 这里通过设置相应的策略,出行的方式也发生了相应的改变.

注意的地方
  1. 首先setTeavelRouteStatus(TravelRoute travelRoute)方法你要是不调用的话,会出项空指针异常的情况,开始的时候我也没有注意到这个问题,但是后来想到之后,这里可能程序上会给用户一个相应的选择,防止用户不选择出现空的情况,其实很简单,只要在相应控制类创建TravelRoute travelRoute的时候直接对应一个对象就可以了.这样即便是你不选择相应的出行方式也会默认有一个出行方式的.
  2. 其实可以不适用接口去创建基类的,比如说你有要子类有一些公共的方法,那么这里你可以把相应的方法提出来,用一个抽象类去实现就好了.

3.2状态模式的使用场景

  • 一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为;
  • 代码中包含大量于对象状态有关的条件语句;
  • 状态模式将每一个条件分支放在一个独立的类中,这似的你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立存在,这样通过多来去除过错的重复的if-else等分支语句

这里举一个项目中实际的例子说明一下:

在项目中但凡有游客模式的情况下,都会涉及到点击相应的按钮要判断相应的登陆逻辑,如果没有登陆的话,去登陆操作,如果登陆的话去到指定的页面!一般的app都是这种逻辑,但是实现的方式就千差万别了.开始的时候我也是各种if-else的判断.

  1. 登陆状态的接口(主要是提供相应的未登录和登陆的相应的实现)
public interface LoginSelect {
    /**
     * author :  贺金龙
     * create time : 2017/12/23 19:20
     * description : 相应状态的实现
     */
    void loginSelect();
}
  1. 相应的登陆的状态
public class LoginStatus implements LoginSelect {
    @Override
    public void loginSelect() {
        System.out.println("已经登陆了,去下一个页面");
    }
}
  1. 相应的未登录的状态
public class NoLoginStatus implements LoginSelect {
    @Override
    public void loginSelect() {
        System.out.println("没有进行登陆,跳转到登陆页面");
    }
}
  1. 相应的控制类
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;
    }
}
  1. 相应的调用
    public static void main(String[] args) {
        LoginControl control = new LoginControl();
        control.loginSelect();
    }

上面就是一个相应的状态模式的实现,这里其实你可以设置多种状态,有的人可能说你写了这么多代码就实现一个这么简单的逻辑,是不是有点小题大作了,其实不然,你想这么一个问题,比如说你们的项目中有这种操作,但是有一天产品跑来加了一种状态,你怎么办,跑到相应的代码的地方是一顿加啊,别问我为什么,因为以前的我干过这么一个事情,别提有多难受了....


其实策略模式和状态模式实现方法都是类似的,在我的理解中,只是两种模式作用不同,其实写法上都差不多,策略模式主要封装的是相应的算法,供用户自行去选择.而状态模式封装的是行为,其实这种行为对于用户来说,可能不知道,但是代码里面已经做了相应的处理了.

写的不好的地方还请大家见谅,有什么问题或者是不对的地方,请及时指出,马上更正

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,923评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,154评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,775评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,960评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,976评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,972评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,893评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,709评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,159评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,400评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,552评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,265评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,876评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,528评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,701评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,552评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,451评论 2 352

推荐阅读更多精彩内容