Java教程

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

本文主要是介绍03 设计模式之状态(行为)模式,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

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

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 设计模式之状态(行为)模式的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!