美文网首页
第二章:状态模式

第二章:状态模式

作者: Benedict清水 | 来源:发表于2020-08-04 14:51 被阅读0次

一、什么是状态模式

故事
水(H2O)有三种状态,冰(固态)、水(液态)、水蒸气(气态)

1.1 模拟状态

对象始终是水(H2O),所以会有一个Water类;而它又有三种状态,我们可以定义为三个状态类:SolidSate、LiquidState、GaseousState;从SolidState、LiquidState、GaseousState这三个单词我们会发现都有一个State后缀,于是想到它们之间的共性,提取一个更抽象的类,这个类就是状态类(State)。

from abc import ABCMeta, abstractmethod


class State(metaclass=ABCMeta):
    """状态类"""

    def __init__(self, name):
        self.__name = name

    def getName(self):
        return self.__name

    @abstractmethod
    def behavior(self, water):
        """不同状态下的行为"""
        pass


class SolidState(State):
    """固态"""

    def __init__(self, name):
        super().__init__(name)

    def behavior(self, water):
        print("我性格高冷,当前体温" + str(water.getTemperature()) + "℃,我坚如钢铁,仿如一个冷血动物,请用我砸人,嘿嘿......")


class LiquidState(State):
    """液态"""

    def __init__(self, name):
        super().__init__(name)

    def behavior(self, water):
        print("我性格温和,当前体温" + str(water.getTemperature()) + "℃,我可滋润万物,引用我可让你活力倍增.......")


class GaseousState(State):
    """气态"""

    def __init__(self, name):
        super().__init__(name)

    def behavior(self, water):
        print("我性格热烈,当前体温" + str(water.getTemperature()) + "℃,飞向天空是我毕生的梦想,在这你将看不到我的存在,我将达到无我的境界......")


class Water:
    """水(H2O)"""

    def __init__(self, state):
        self.__temperature = 25  # 默认温度25℃
        self.__state = state

    def setState(self, state):
        self.__state = state

    def changeState(self, state):
        if self.__state:
            print("由", self.__state.getName(), "变为", state.getName())
        else:
            print("初始化为", state.getName())
        self.setState(state)

    def getTemperature(self):
        return self.__temperature

    def setTemperature(self, temperature):
        self.__temperature = temperature
        if self.__temperature <= 0:
            self.changeState(SolidState("固态"))
        elif self.__temperature <= 100:
            self.changeState(LiquidState("液态"))
        else:
            self.changeState(GaseousState("气态"))

    def riseTemperature(self, step):
        self.setTemperature(self.__temperature + step)

    def reduceTemperature(self, step):
        self.setTemperature(self.__temperature - step)

    def behavior(self):
        self.__state.behavior(self)


def testState():
    water = Water(LiquidState("液态"))
    water.behavior()
    water.setTemperature(-4)
    water.behavior()
    water.riseTemperature(18)
    water.behavior()
    water.riseTemperature(110)
    water.behavior()
    water.reduceTemperature(150)
    water.behavior()


if __name__ == "__main__":
    testState()

% python water.py

我性格温和,当前体温25℃,我可滋润万物,引用我可让你活力倍增.......
由 液态 变为 固态
我性格高冷,当前体温-4℃,我坚如钢铁,仿如一个冷血动物,请用我砸人,嘿嘿......
由 固态 变为 液态
我性格温和,当前体温14℃,我可滋润万物,引用我可让你活力倍增.......
由 液态 变为 气态
我性格热烈,当前体温124℃,飞向天空是我毕生的梦想,在这你将看不到我的存在,我将达到无我的境界......
由 气态 变为 固态
我性格高冷,当前体温-26℃,我坚如钢铁,仿如一个冷血动物,请用我砸人,嘿嘿......

在setTemperature方法中,检测到不同温度,Water的__state被赋值为不同对象,之后Water的behavior方法就可以调用不同对象的behavior方法,实现了Water对象在其内部改变行为,看上去就像Water改变类型的效果。

二、状态模式的定义

2.1定义

允许一个对象在其内部状态发生改变时改变其行为,使这个对象看上去就像改变了它的类型一样

如水一般,状态即事物所处的某一种状态,状态模式是说一个对象在其内部状态发生改变时,其表现的行为和外在属性不一样,这个对像看上去就像改变了它的类型一样,因此,状态模式又称为对象的行为模式。

2.2 设计思想

状态模式的核心思想就是一个事物(对象)有多种状态,在不同的状态下所表现出来的行为和属性不一样。

2.3状态模式的模型抽象

(1) Water的setTemperature(self, temperature)方法不符合程序设计中的开放封闭原则。虽然水只有三种状态,但在其他的应用场景中可能会有更多的状态,如果再加一个状态(state),则要在setTemperature中再增加一个if else判断。
(2) 表示状态的类应该只会有一个实例,因为不可能出现“固态1”“固态2”的情形,所以状态类的实现要使用单例模式。

2.4 状态模式的框架模型 stateframe.py
from abc import ABCMeta, abstractmethod


class Context(metaclass=ABCMeta):
    """状态模式的上下文环境类"""

    def __init__(self):
        self.__states = []
        self.__curState = None
        # 状态发生变化依赖的属性,当这一变量由多个变量共同决定时可以将其单独定义成一个类
        self.__stateInfo = 0

    def addState(self, state):
        if state not in self.__states:
            self.__states.append(state)

    def changeState(self, state):
        if state is None:
            return False
        if self.__curState is None:
            print("初始化为", state.getName())
        else:
            print("由", self.__curState.getName(), "变为", state.getName())
        self.__curState = state
        self.addState(state)
        return True

    def getState(self):
        return self.__curState

    def _setStateInfo(self, stateInfo):
        self.__stateInfo = stateInfo
        for state in self.__states:
            if state.isMatch(stateInfo):
                self.changeState(state)

    def __getstateInfo(self):
        return self.__stateInfo


class State:
    """状态类的基类"""

    def __init__(self, name):
        self.__name = name

    def getName(self):
        return self.__name

    def isMatch(self, stateInfo):
        "状态的属性stateInfo是否在当前的状态范围内"
        return False

    @abstractmethod
    def behavior(self, context):
        pass

state是抽象状态(基类),负责状态的定义和接口的统一。
Context是上下文环境类,负责具体状态的切换。

三、基于框架的实现

from stateframe import Context, State


def singleton(cls, *args, **kwargs):
    "构造一个单例的装饰器"
    instance = {}

    def __singleton(*args, **kwargs):
        if cls not in instance:
            instance[cls] = cls(*args, **kwargs)
        return instance[cls]

    return __singleton


@singleton
class SolidState(State):
    """固态"""
    def __init__(self, name):
        super().__init__(name)

    def isMatch(self, stateInfo):
        return stateInfo < 0

    def behavior(self, context):
        print("我性格高冷,当前体温" + str(context._getStateInfo()) + 
              "℃,我坚如钢铁,仿如一个冷血动物,请用我砸人,嘿嘿......")

@singleton
class LiquidState(State):
    """液态"""

    def __init__(self, name):
        super().__init__(name)

    def isMatch(self, stateInfo):
        return (stateInfo >= 0 and stateInfo < 100)

    def behavior(self, context):
        print("我性格温和,当前体温" + str(context._getStateInfo()) + 
              "℃,我可滋润万物,引用我可让你活力倍增.......")


class GaseousState(State):
    """气态"""

    def __init__(self, name):
        super().__init__(name)

    def isMatch(self, stateInfo):
        return stateInfo >= 100

    def behavior(self, context):
        print("我性格热烈,当前体温" + str(context._getStateInfo()) + 
              "℃,飞向天空是我毕生的梦想,在这你将看不到我的存在,我将达到无我的境界......")


class Water(Context):
    """水(H20)"""

    def __init__(self):
        super().__init__()
        self.addState(SolidState("固态"))
        self.addState(LiquidState("液态"))
        self.addState(GaseousState("气态"))
        self.setTemperature(25)

    def getTemperature(self):
        return self._getStateInfo()

    def setTemperature(self, temperature):
        self._setStateInfo(temperature)

    def riseTemperature(self, step):
        self.setTemperature(self.getTemperature() + step)

    def reduceTemperature(self, step):
        self.setTemperature(self.getTemperature() - step)

    def behavior(self):
        state = self.getState()
        if isinstance(state, State):
            state.behavior(self)


def testState():
    water = Water()
    water.behavior()
    water.setTemperature(-4)
    water.behavior()
    water.riseTemperature(18)
    water.behavior()
    water.riseTemperature(110)
    water.behavior()
    water.reduceTemperature(150)
    water.behavior()


if __name__ == "__main__":
    testState()

% python waterstate.py

初始化为 液态
我性格温和,当前体温25℃,我可滋润万物,引用我可让你活力倍增.......
由 液态 变为 固态
我性格高冷,当前体温-4℃,我坚如钢铁,仿如一个冷血动物,请用我砸人,嘿嘿......
由 固态 变为 液态
我性格温和,当前体温14℃,我可滋润万物,引用我可让你活力倍增.......
由 液态 变为 气态
我性格热烈,当前体温124℃,飞向天空是我毕生的梦想,在这你将看不到我的存在,我将达到无我的境界......
由 气态 变为 固态
我性格高冷,当前体温-26℃,我坚如钢铁,仿如一个冷血动物,请用我砸人,嘿嘿......
3.1 设计要点:

(1) 在实现状态模式的时候,实现的场景状态有时候会非常的复杂,决定状态变化的因素非常多,我可以把决定状态变化的属性单独抽象成一个类StateInfo,这样判断状态属性是否符合当前的状态isMatch时就可以传入更多的信息。
(2) 每一种状态应当只有唯一的实例。

3.2 优缺点:

优点:
(1). 封装了状态的转换规则,在状态模式中可以将状态的转换代码封装在环境类中,对状态转换代码进行集中管理,而不是分散在一个个业务逻辑中。
(2). 将所有与某个状态有关的行为放到一个类中(称为状态类),使开发人员只专注于改状态下的逻辑开发。
(3). 允许状态转换逻辑与状态对象合为一体,使用时只需要注入一个不同状态的对象即可使环境对象拥有不同的行为。
缺点:
(1).会增加系统类和对象的个数。
(2). 状态模式的结构与实现都较为复杂,如果使用不当容易导致程序结构和代码的混乱。

3.3 应用场景

(1) 一个对象的行为取决于它的状态,并且它在运行的时可能经常改变它的状态,从而改变它的行为。
(2) 一个操作中含有庞大的多分支的条件语句,这些分支依赖于该对象的状态,且每一个分支的业务逻辑都非常复杂时,我们可以使用状态模式来拆分不同分支逻辑,使程序有更好的可读性和可维护性。

以上为个人学习笔记:
《人人都懂设计模式》作者:罗伟富

相关文章

  • 第二章:状态模式

    一、什么是状态模式 故事水(H2O)有三种状态,冰(固态)、水(液态)、水蒸气(气态) 1.1 模拟状态 对象始终...

  • 《今日TA》8.25 线上读书会纪要

    内容:第二章《自我状态模式》 “自我状态是名称,不是实物”和“措辞问题:‘只有三个’自我状态吗?”两节 页码:P2...

  • State模式

    状态模式(State模式) 定义 状态模式,又称状态对象模式(Pattern of Objects for S...

  • 设计模式-状态模式

    设计模式-状态模式 设计模式 状态模式的关键是区分事物内部的状态

  • 状态模式(状态机模式)

    状态模式学习笔记 前言:文章从三方面简单阐述状态模式:是什么、为什么、如何做。这是我在工作之余自己的一些理解、思考...

  • C++设计模式(3)

    本文预览: 状态模式 组合模式 迭代器 职责链 命令 状态模式 定义:状态模式(State Pattern),允许...

  • 设计模式——状态模式

    定义 状态模式,又称状态对象模式(Pattern of Objects for States),状态模式是对象的行...

  • 第5章 -行为型模式-状态模式

    一、状态模式的简介 二、状态模式的优缺点 三、状态模式的实例

  • 状态模式

    Android进阶之设计模式 状态模式 定义: 当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了...

  • 状态模式

    状态模式:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。允许对象随着状态改变而改变行为。 策略...

网友评论

      本文标题:第二章:状态模式

      本文链接:https://www.haomeiwen.com/subject/uhzcrktx.html