ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

03 设计模式之状态(行为)模式

2021-08-26 22:03:45  阅读:128  来源: 互联网

标签:03 .__ curState self 模式 state stateInfo 设计模式 def


设计模式之状态(行为)模式

1. 场景模拟

# 模拟水的三种不同状态及其相互转化
    # 固态、液态、气态
# 不管是什么状态 都是水

# water类、 SolidState、 LiquiState、 GaseousState(固,液,气)、 state类

# 思想:温度变化会改变状态,不同状态下有不同的行为特征

1.1 初始代码

from abc import ABCMeta, abstractmethod

class Water:
    """水"""
    def __init__(self, state):
        self.__temperature = 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.__state = 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(LiquiState("液态"))
        else:
            self.changeState(GaseousState("气态"))

    def riseTemperature(self, step):          # 温度上升
        self.setTemperature(self.__temperature + step)

    def declineTemperature(self, step):       # 温度下降
        self.setTemperature(self.__temperature - step)

    def behavior(self):
        # self.__state 就是状态实例化对象(谁来调用就是谁 然后调用不同状态下的behavior方法 固液气 )
        self.__state.behavior(self)
        # print(self.__state)

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 LiquiState(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()))

def testState():
    # print(LiquiState("液态"))
    water = Water(LiquiState("液态"))         # 实例化water  ,将一个状态的实例化对象传进去=state
    water.behavior()                         # 核心
    # 不管是上升、下降温度或者直接设置温度,都是为了确定温度属于哪一个状态,然后改变状态。通过不同状态来调用不同的行为(behavior)
    water.riseTemperature(100)
    water.behavior()
    # water.setTemperature(-4)
    # water.behavior()
    # water.setTemperature(18)
    # water.behavior()
    # water.setTemperature(110)
    # water.behavior()

testState()

1.2 以上代码存在的问题

    1. setTemperature方法不符合设计中的开放封闭原则,其他场景会有更多中状态,如果加一种状态,就需要多加一个elif判断
    1. 表示状态的类只会有一种实例,因为不可能出现固态1,固态2,所以状态需要用到单例模式

2. 代码改进

2.1 状态模式类图

image

2.2 针对以上问题提出代码框架

from abc import ABCMeta, abstractmethod

class Context(metaclass=ABCMeta):
    """状态模式的上下文环境类"""
    def __init__(self):
        self.__states = []          # 装着各个状态的实例化对象
        self.__curState = None      # self.__curState就是状态的实例化对象(谁来就是谁)
        # 状态变化依赖的属性,当这一个变量由多个变量共同决定时可以将其定义成一个类
        self.__stateInfo = 0

    def addState(self, state):      # 如果状态不在self.__states中,加进去
        if state not in self.__states:
            self.__states.append(state)

    def changState(self, state):            # 改变状态
        if state is None:
            return False
        print(self.__curState)
        if self.__curState is None:
            print("初始化", state.getName())
        else:
            print("由",self.__curState.getName(), "变为", state.getName())
        self.__curState = state                 # 在这对self.__curState 进行改变,开始是none,后面谁需要改变状态就是谁
        return True

    def getState(self):
        return self.__curState

    def _setStateInfo(self, stateInfo):       # 初始 stateInfo = 25
        self.__stateInfo = stateInfo
        # 每一个状态都判断 25 是不是属于自身范围内的。 isMatch(stateInfo) 返回 true/false
        # ps:    stateInfo < 0  25<0   false
        for state in self.__states:
            if state.isMatch(stateInfo):      # 如果在其中一个的范围,则将原来的状态变成现在确定的状态
                self.changState(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

2.3 改进代码如下

from abc import ABCMeta, abstractmethod

class Context(metaclass=ABCMeta):
    """状态模式的上下文环境类"""
    def __init__(self):
        self.__states = []          # 装着各个状态的实例化对象
        self.__curState = None      # self.__curState就是状态的实例化对象(谁来就是谁)
        # 状态变化依赖的属性,当这一个变量由多个变量共同决定时可以将其定义成一个类
        self.__stateInfo = 0

    def addState(self, state):      # 如果状态不在self.__states中,加进去
        if state not in self.__states:
            self.__states.append(state)

    def changState(self, state):            # 改变状态
        if state is None:
            return False
        print(self.__curState)
        if self.__curState is None:
            print("初始化", state.getName())
        else:
            print("由",self.__curState.getName(), "变为", state.getName())
        self.__curState = state                 # 在这对self.__curState 进行改变,开始是none,后面谁需要改变状态就是谁
        return True

    def getState(self):
        return self.__curState

    def _setStateInfo(self, stateInfo):       # 初始 stateInfo = 25
        self.__stateInfo = stateInfo
        # 每一个状态都判断 25 是不是属于自身范围内的。 isMatch(stateInfo) 返回 true/false
        # ps:    stateInfo < 0  25<0   false
        for state in self.__states:
            if state.isMatch(stateInfo):      # 如果在其中一个的范围,则将原来的状态变成现在确定的状态
                self.changState(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

class Water(Context):
    """水"""
    def __init__(self):
        super().__init__()                # 继承父类的全部初始化信息
        # 将各个状态的实例化对象放到self.__states=[]  中
        self.addState(SolidState("固态"))
        self.addState(LiquiState("液态"))
        self.addState(GaseousState("气态"))
        # 设置初始温度为 25
        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 declineTemperature(self, step):       # 温度下降
        self.setTemperature(self.getTemperature() - step)

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

# 单例装饰器
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("固态", context._getStateInfo())


class LiquiState(State):
    """液态"""
    def __init__(self, name):
        super().__init__(name)

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

    def behavior(self, context):
        print("液态", context._getStateInfo())


class GaseousState(State):
    """气态"""
    def __init__(self, name):
        super().__init__(name)

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

    def behavior(self, context):
        print("气态", context._getStateInfo())


def testState():
    # print(LiquiState("液态"))
    water = Water()                     # 初始化
    # water.behavior()
    # water.riseTemperature(100)
    # water.behavior()
    water.setTemperature(-4)            # 设置温度,目的改变状态
    water.behavior()                    # 不同状态下的不同行为
    # water.setTemperature(18)
    # water.behavior()
    # water.setTemperature(110)
    # water.behavior()

testState()

"""最少需要三步"""

注意: 实际场景状态复杂时,可以用一个类去定义stateInfo, 每一种状态只有唯一的实例(单例模式限制)

3. 应用场景

  • 一个对象的行为取决于它的状态,并且运行时可能经常改变他的状态,从而改变它的行为

标签:03,.__,curState,self,模式,state,stateInfo,设计模式,def
来源: https://www.cnblogs.com/yebaoer/p/15191620.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有