首页 > 其他分享 >2.状态模式

2.状态模式

时间:2022-09-02 15:57:10浏览次数:67  
标签:__ 状态 self 模式 state lift print def

一、状态模式

状态模式的定义如下:当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类。

二、状态模式的优点和应用场景

优点:
1、状态模式的优点是结构清晰,相比于if…else…简约了不少;
2、封装性好,外部调用不必知道内部实现细节。
应用场景:
1、行为状态改变的场景。这点在各种控制器中非常常见,同时,逻辑结构为状态转移图的场景中都非常适用。

三、状态模式的缺点

1、在状态比较多时,子类也会非常多,不便于管理。

四、示例

例1:电梯控制器

电梯在我们周边随处可见,电梯的控制逻辑中心是由电梯控制器实现的。电梯的控制逻辑,即使简单点设计,把状态分成开门状态,停止状态和运行状态,操作分成开门、关门、运行、停止,那流程也是很复杂的。首先,开门状态不能开门、运行、停止;停止状态不能关门,停止;运行状态不能开门、关门、运行。要用一个一个if…else…实现,首先代码混乱,不易维护;二是不易扩展。至于各种设计原则什么的……
那该如何实现?在上边的逻辑中,每个操作仅仅是一个操作,状态切换与操作是分离的,这也造成后来操作和状态“相互配合”的“手忙脚乱”。如果把状态抽象成一个类,每个状态为一个子类,每个状态实现什么操作,不实现什么操作,仅仅在这个类中具体实现就可以了。
下面我们实现这个逻辑。

先实现抽象的状态类:

class LiftState:
    def open(self):
        pass
    def close(self):
        pass
    def run(self):
        pass
    def stop(self):
        pass

而后实现各个具体的状态类:

class OpenState(LiftState):
    def open(self):
        print "OPEN:The door is opened..."
        return self
    def close(self):
        print "OPEN:The door start to close..."
        print "OPEN:The door is closed"
        return StopState()
    def run(self):
        print "OPEN:Run Forbidden."
        return self
    def stop(self):
        print "OPEN:Stop Forbidden."
        return self
class RunState(LiftState):
    def open(self):
        print "RUN:Open Forbidden."
        return self
    def close(self):
        print "RUN:Close Forbidden."
        return self
    def run(self):
        print "RUN:The lift is running..."
        return self
    def stop(self):
        print "RUN:The lift start to stop..."
        print "RUN:The lift stopped..."
        return StopState()
class StopState(LiftState):
    def open(self):
        print "STOP:The door is opening..."
        print "STOP:The door is opened..."
        return OpenState()
    def close(self):
        print "STOP:Close Forbidden"
        return self
    def run(self):
        print "STOP:The lift start to run..."
        return RunState()
    def stop(self):
        print "STOP:The lift is stopped."
        return self

为在业务中调度状态转移,还需要将上下文进行记录,需要一个上下文的类。

class Context:
    lift_state=""
    def getState(self):
        return self.lift_state
    def setState(self,lift_state):
        self.lift_state=lift_state
    def open(self):
        self.setState(self.lift_state.open())
    def close(self):
        self.setState(self.lift_state.close())
    def run(self):
        self.setState(self.lift_state.run())
    def stop(self):
        self.setState(self.lift_state.stop())

这样,在进行电梯的调度时,只需要调度Context就可以了。业务逻辑中如下所示:

if __name__=="__main__":
    ctx = Context()
    ctx.setState(StopState())
    ctx.open()
    ctx.run()
    ctx.close()
    ctx.run()
    ctx.stop()

打印如下:

STOP:The door is opening...
STOP:The door is opened...
OPEN:Run Forbidden.
OPEN:The door start to close...
OPEN:The dorr is closed
STOP:The lift start to run...
RUN:The lift start to stop...
RUN:The lift stopped...

由逻辑中可知,电梯先在STOP状态,然后开门,开门时运行Run,被禁止,然后,关门、运行、停止。

例2:电视机开机,关机

# -*- coding: utf-8 -*-

from abc import ABCMeta, abstractmethod


class State(metaclass=ABCMeta):
    @abstractmethod
    def do_this(self):
        pass


class StartState(State):
    def do_this(self):
        print("start state")


class StopState(State):
    def do_this(self):
        print("stop state")


class TVContext(State):
    def __init__(self):
        self.state = None

    def get_state(self):
        return self.state

    def set_state(self, state):
        self.state = state

    def do_this(self):
        self.state.do_this()


if __name__ == '__main__':
    context = TVContext()

    start = StartState()
    stop = StopState()

    context.set_state(start)
    context.do_this()

    context.set_state(stop)
    context.do_this()
"""
start state
stop state
"""

例子3:电脑开机,待机,关机

# -*- coding: utf-8 -*-

# 接口
class ComputerState(object):
    name = "state"
    allowed = []

    def switch(self, state):
        if state.name in self.allowed:
            print("switch state: {}".format(state.name))
            self.__class__ = state
        else:
            print("state not allowed")

    def __str__(self):
        return self.name

    
# 开机
class On(ComputerState):
    name = "on"
    allowed = ["off", "hibernate"]


# 关机
class Off(ComputerState):
    name = "off"
    allowed = ["on"]


# 休眠
class Hibernate(ComputerState):
    name = "hibernate"
    allowed = ["on", "off"]


# 客户端
class Computer(object):
    def __init__(self):
        self.state = Off()  # 初始状态是关机状态

    def change(self, state):
        self.state.switch(state)


if __name__ == '__main__':
    computer = Computer()

    # 开机 -> 休眠 -> 关机
    computer.change(On)
    computer.change(Hibernate)
    computer.change(Off)

    # 关机的请情况下休眠
    computer.change(Hibernate)
"""
switch state: on
switch state: hibernate
switch state: off

state not allowed
"""

标签:__,状态,self,模式,state,lift,print,def
From: https://www.cnblogs.com/amgulen/p/16650186.html

相关文章

  • 【计算讲谈社】第十一讲|商用车智能驾驶商业化实践:“科技+保险”模式探索
    自动驾驶的“玩家”们持续在探索技术的应用场景和商业化落地。商用车智能驾驶企业所托瑞安从“科技+保险”切入,探索出一条自动驾驶商业化的道路。【计算讲谈社】第十一讲......
  • Redis集群模式哈希槽rename问题
    (error)ERR'RENAME'commandkeysmustinsameslot一、介绍我们先来看基本的介绍RedisRename命令用于修改key的名称。1、语法redisrename命令的基本用法如......
  • java Builder模式
    Builder 模式也叫建造者模式,builder模式的作用将一个复杂对象的构建与他的表示分离,一步一步创建一个复杂对象的创建型模式。在不知道内部建造细节的情况下,可以更精细的控......
  • php webman对接Luckysheet share多人协作模式项目
    2022年9月2日10:05:03gitee地址https://gitee.com/zxadmin/luckysheet-phpserver此项目目前定义为对接失败,当然Luckysheet也可以去除掉加密的部分,直接json通信就没问题......
  • SparkStreaming中的转换算子2--有状态的转换算子updateStateByKey
    将之前批次的状态保存,packageSparkStreaming.transimportorg.apache.spark.SparkConfimportorg.apache.spark.storage.StorageLevelimportorg.apache.spark.str......
  • PCIe的RC模式和EP模式有什么区别?
    1、RC:RootComplexRC设备用于连接CPU/内存子系统和I/O设备;RC模式下,PCIE配置头中的类型值为1;RC模式下,支持配置和I/O事务2、EP:EndPointEP设备通常表示一个串行或I/......
  • 设计模式之(7)——装饰设计模式
    定义:装饰设计模式允许向一个现有的对象添加功能,而不改变其结构(这就很符合程序设计的“开闭原则”),重点突出类功能的增强,属于结构型创建模式,这种模式创建了一个装饰类,用......
  • 拼多多的电子商务盈利模式分析
    拼多多是一家基于 C2B 拼团营销方式主营团购的电商平台,其盈利模式由利润源、利润点、利润杠杆、利润通道和利润屏障五个要素组成的。通过锁定目标客户、关注客户价值、举......
  • android原生观察者和被观察者模式java.util.Observable
    项目中用到这个,所以记录一下https://blog.csdn.net/iteye_5649/article/details/82636534?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidula......
  • 2. 对比redis的RDB、AOF模式的优缺点
    2. 对比redis的RDB、AOF模式的优缺点 2.1 redis的RDB模式2.1.1RDB模式工作原理  RDB(RedisDataBase):基于时间的快照,其默认只保留当前最新的一次快照,特点......