状态模式:允许一个对象在其内部状态发生改变时改变其行为,使这个对象看上去就像改变了它的类型一样。
生活中的设计模式:比如你最近你是一个减肥中的吃货,你决定每天开始跑。,但是你跑了步后总是嘴馋,所以你跟你自己默默的做了一个约定。跑小于2公里以下时,不能吃任何东西;跑2~3公里,跑完能吃一根香蕉;跑3~4公里,跑玩能吃一个苹果;跑了4~5公里,能吃一个红薯;跑大于5公里时,能吃一个汉堡。
此案例,跑步的里程可以当作对象内部的状态改变,随着跑步里程的不同,所能吃的食物也不一样;代码如下:
from abc import ABCMeta, abstractmethod
class Running(metaclass=ABCMeta):
"""跑步里程抽象类"""
def __init__(self):
self.__state = []
self.__current_state = None
self.__miles = 0
def add_state(self, state):
if state not in self.__state:
self.__state.append(state)
def change_state(self, state):
if state is None:
return False
if self.__current_state is None:
print("Init: ", state.get_name())
else:
print("State has changed: {0} --> {1}".format(self.get_state().get_name(), state.get_name()))
self.__current_state = state
self.add_state(state)
def get_state(self):
return self.__current_state
def _set_running_miles(self, miles):
self.__miles = miles
print("Running miles: ", self.__miles)
for state in self.__state:
if state.is_match(self.__miles):
self.change_state(state)
def _get_running_miles(self):
return self.__miles
class Miles(Running):
"""跑步里程类"""
def __init__(self):
super().__init__()
self.add_state(EatAir("空气"))
self.add_state(EatBanana("香蕉"))
self.add_state(EatApple("苹果"))
self.add_state(EatSweetPotato("红薯"))
self.add_state(EatHamburger("汉堡"))
self.set_miles(0)
def increase_miles(self, miles):
self.set_miles(self._get_running_miles() + miles)
def decrease_miles(self, miles):
self.set_miles(self._get_running_miles() - miles)
def set_miles(self, miles):
return self._set_running_miles(miles)
def eat(self):
self.get_state().eat()
class Eat:
"""吃东西类"""
def __init__(self, name):
self.__name = name
@abstractmethod
def eat(self):
pass
def get_name(self):
return self.__name
class EatAir(Eat):
"""吃空气"""
def __init__(self, name):
super().__init__(name)
def eat(self):
print("Eat Air.")
def is_match(self, mile):
return mile <= 2
class EatBanana(Eat):
"""吃香蕉"""
def __init__(self, name):
super().__init__(name)
def eat(self):
print("Eat Banana.")
def is_match(self, mile):
return 2 < mile <= 3
class EatApple(Eat):
"""吃苹果"""
def __init__(self, name):
super().__init__(name)
def eat(self):
print("Eat Apple.")
def is_match(self, mile):
return 3 < mile <= 4
class EatSweetPotato(Eat):
"""吃红薯"""
def __init__(self, name):
super().__init__(name)
def eat(self):
print("Eat SweetPotato.")
def is_match(self, mile):
return 4 < mile <= 5
class EatHamburger(Eat):
"""吃汉堡"""
def __init__(self, name):
super().__init__(name)
def eat(self):
print("Eat Hamburger.")
def is_match(self, mile):
return 5 < mile
def test():
"""测试方法"""
runing_miles = Miles()
runing_miles.eat()
runing_miles.increase_miles(5)
runing_miles.eat()
runing_miles.decrease_miles(1)
runing_miles.eat()
runing_miles.increase_miles(2)
runing_miles.eat()
runing_miles.decrease_miles(3)
runing_miles.eat()
test()
其实单纯从上述案例的需求来说,IF -- ELSE
可能是更好的选择;因为上述案例的对象的属性状态简单,并不复杂,判断起来比较简单;但是当对象属性状态复杂的情形下,状态模式就能排上用场了。
状态模式的应用场景:(1)一个对象的行为取决于它的状态,并且它在运行时可能经常改变它的状态,从而改变它的行为。
(2)一个操作中含有庞大的多分支条件语句,这些分支以来于该对象的状态,且每一个分支的业务逻辑都非常复杂时,我们可以使用状态模式来拆分不同的分支逻辑,使程序有更好的可读性和可维护性。