为了账号安全,请及时绑定邮箱和手机立即绑定

聊一聊策略模式和状态模式

2020.05.05 21:15 4549浏览

前言

在行为型设计模式中,策略模式和状态模式在结构上非常的类似,并且在逻辑简化,去耦合上都是一个很好的解决方案。

有些小伙伴经常会分不清两者的区别,本文将来聊聊这两种模式。

本章节用 typescript 进行书写。

相同点

本质上,策略模式和状态模式都是干同一个事情,那就是去耦合。换句话说,就是把关注点进行分离,干什么以及怎么干分别放在不同的地方实现,从而减少我们逻辑上的耦合,也让我们的程序不用陷入 if...else.. 地狱中去。

策略模式

策略模式,就是用什么策略干什么事情。简单来说,策略模式就是我们定义了一系列的算法,算法间彼此独立可切换。而关于如何使用这些策略,则由上层调用者来进行实现,非常灵活。

举个栗子

我们知道每个人的职责是不同的,比方说,学生的工作就是学习,农民的工作就是务农,医生的工作就是救死扶伤。那么,对于不同的身份,我们可以赋予不同的策略算法。

策略

首先,我们需要定义一批策略方法。

interface Istrategies {
    [key: string]: () => any
}

const strategies: Istrategies = {
    student: function () {
        console.log('我在读书')
    },
    doctor: function () {
        console.log('我在治病')
    },
    farmer: function () {
        console.log('我在干农活')
    }
}

我们使用了对象来模拟一些列的策略类,并实现了 Istrategies 接口。其次,我们要实现一个环境类,对外提供调用接口。

对外接口

interface IstrategiesCtx {
    work:(name: string) => void;
}

const strategiesCtx: IstrategiesCtx = (function () {
    return {
        work: function (name: string) {
            strategies[name] && strategies[name].call(this)
        }
    }
})()

环境我们使用即时执行函数来模拟,导出接口。这样,我们就可以在任何地方随意切换使用了。

调用

strategiesCtx.work('student')

strategiesCtx.work('farmer')

strategiesCtx.work('doctor')

结果

http://img2.sycdn.imooc.com/5eb166730001f77808690059.jpg

状态模式

使用策略模式,我们想怎么切换怎么调用都行,强调了一个自主性。现在,我们希望自己维护一些状态,然后不再关心如何去调用了,也就是说我们把自主权转移给了第三方,而自己并不关心。

还是上面那个例子,我们分别对应着学生、医生和农民三个身份,不同身份状态下,我们都可以工作,只不过工作的东西就不一样了。

有限状态机

首先,我们实现一下我们的几种状态,内部维护状态,并且提供切换状态以及工作的接口。

interface IprofessionState {
    change(val: string): void
    work(): void

}
interface Ijob {
    work (): void
}

interface Istate {
    [key: string]: Ijob
}

const professionState: IprofessionState = (function() {
    let state = 'student'
    const _state: Istate = {
        student: {
            work: function () {
                console.log('我正在读书')
            }
        },
        farmer: {
            work: function () {
                console.log('我正在干农活')
            }
        },
        doctor: {
            work: function () {
                console.log('我在治病')
            }
        }
    }
    return {
        change: function (val) {
            state = val
        },
        work: function () {
            _state[state] && _state[state].work.call(this)
        }
    }
})()

其中,我们分别定义了三种状态,并且每一种状态都提供和一个 work方法。其次,对外的 change 方法可以切换状态, 而 work 则是当前状态的工作方法。

调用

关于调用,我们可以实现一个 Person 类。

class Person {
    private role: any
    constructor (role) {
        this.role = role
    }
    change (roleName) {
        this.role.change(roleName)
    }
    handleWork () {
        this.role.work()
    }
}

const xiaoming = new Person(professionState)
xiaoming.handleWork()

xiaoming.change('doctor')
xiaoming.handleWork()

xiaoming.change('farmer')
xiaoming.handleWork()


Person 内部持有 role,持有状态。当我们调用 change 赋予不同的角色时,handleWork 会有不同的表现。

结果

http://img1.sycdn.imooc.com/5eb166740001b24607870057.jpg

总结

总的来说,策略模式和状态模式还是有很多的相似之处,它们在结构上有很多类似的地方,同时都是去耦合的绝佳方式。在我们日常开发中,善用这两种模式都能够很好的分离关注点,也可以避免很多 if 分支的使用。

不同的是,策略模式讲究一批策略算法可以灵活切换,并且彼此独立。在调用方式上也都是主观程序控制,主动调用不同的策略来实现不同的功能,不需要维护一个状态。

而状态模式最大不同在于,状态模式会维护一个状态,并且不关心当前使用了哪一个算法,只需要切换到不同的状态,行为自然不同。这里敲黑板,切换状态,改变行为

在线直通车

聊一聊策略模式和状态模式

点击查看更多内容

本文原创发布于慕课网 ,转载请注明出处,谢谢合作

1人点赞

若觉得本文不错,就分享一下吧!

评论

相关文章推荐

正在加载中
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消