[Python设计模式] 第16章 上班,干活,下班,加班——状态模式
github地址:https://github.com/cheesezh/python_design_patterns
题目
用代码模拟一天的工作状态,上午状态好,中午想睡觉,下午渐恢复,加班苦煎熬。
基础版本——函数版
hour = 0
work_finished = False
def write_program():
if hour < 12:
print("当前时间: {} 点, 上午工作,精神百倍".format(hour))
elif hour < 13:
print("当前时间: {} 点, 饿了,午饭,犯困,午休".format(hour))
elif hour < 17:
print("当前时间: {} 点, 下午状态还可以,继续努力".format(hour))
elif work_finished == True:
print("当前时间: {} 点, 收工,下班".format(hour))
elif hour < 21:
print("当前时间: {} 点, 加班中,好累".format(hour))
else:
print("当前时间: {} 点, 不行了,睡着了".format(hour))
hour = 9
write_program()
hour = 10
write_program()
hour = 12
write_program()
hour = 13
write_program()
hour = 14
write_program()
hour = 17
work_finished = True
# work_finished = False
write_program()
hour = 19
write_program()
hour = 22
write_program()
当前时间: 9 点, 上午工作,精神百倍
当前时间: 10 点, 上午工作,精神百倍
当前时间: 12 点, 饿了,午饭,犯困,午休
当前时间: 13 点, 下午状态还可以,继续努力
当前时间: 14 点, 下午状态还可以,继续努力
当前时间: 17 点, 收工,下班
当前时间: 19 点, 收工,下班
当前时间: 22 点, 收工,下班
改进版本1.0——初步封装
class Work():
def __init__(self):
self.hour = 0
self.task_finished = False
def write_program(self):
if self.hour < 12:
print("当前时间: {} 点, 上午工作,精神百倍".format(self.hour))
elif self.hour < 13:
print("当前时间: {} 点, 饿了,午饭,犯困,午休".format(self.hour))
elif self.hour < 17:
print("当前时间: {} 点, 下午状态还可以,继续努力".format(self.hour))
elif self.work_finished == True:
print("当前时间: {} 点, 收工,下班".format(self.hour))
elif self.hour < 21:
print("当前时间: {} 点, 加班中,好累".format(self.hour))
else:
print("当前时间: {} 点, 不行了,睡着了".format(self.hour))
work = Work()
work.hour = 9
work.write_program()
work.hour = 10
work.write_program()
work.hour = 12
work.write_program()
work.hour = 13
work.write_program()
work.hour = 14
work.write_program()
work.hour = 17
work.work_finished = True
# work_finished = False
work.write_program()
work.hour = 19
work.write_program()
work.hour = 22
work.write_program()
当前时间: 9 点, 上午工作,精神百倍
当前时间: 10 点, 上午工作,精神百倍
当前时间: 12 点, 饿了,午饭,犯困,午休
当前时间: 13 点, 下午状态还可以,继续努力
当前时间: 14 点, 下午状态还可以,继续努力
当前时间: 17 点, 收工,下班
当前时间: 19 点, 收工,下班
当前时间: 22 点, 收工,下班
点评
- 这个类中的write_program方法过长,而且有很多判断分支,意味着它的责任过大了。面向对象设计其实就是希望做到代码的责任分解。所以这个类违背了
单一职责原则
; - 此外,write_program方法里有这么多判断,使得任何需求的改动或增加,都需要去更改这个方法。所以这个类也违背了
开放-封闭原则
;
状态模式
状态模式,当一个对象的内在状态改变是允许改变其行为,这个对象看起来像是改变了其类。[DP]
状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。
from abc import ABCMeta, abstractmethod
class State():
__metaclass__ = ABCMeta
@abstractmethod
def handle(self, context):
pass
class StateA(State):
def handle(self, context):
context.set_state(StateB())
class StateB(State):
def handle(self, context):
context.set_state(StateA())
class Context():
def __init__(self, state):
self.state = state
def set_state(self, state):
self.state = state
print("当前状态: {}".format(self.state.__class__))
def request(self):
self.state.handle(self) # 精髓
def main():
context = Context(StateA())
context.request()
context.request()
context.request()
context.request()
main()
当前状态: <class '__main__.StateB'>
当前状态: <class '__main__.StateA'>
当前状态: <class '__main__.StateB'>
当前状态: <class '__main__.StateA'>
状态模式的好处与用处
状态模式的好处是将与特定状态相关的行为局部化,并且将不同状态的行为分割开来。[DP]就是将特定的状态相关的行为都放入一个对象中,由于所有与状态相关的代码都存在于某个ConcretState中,所以通过定义新的子类可以很容易的增加新的状态和转换[DP]。这样做的目的就是为了消除庞大的条件分支语句,大的分支判断会使得它们难以修改和扩展。状态模式通过把各种状态转移逻辑分不到State的子类之间,来减少相互之间的依赖。
什么时候需要考虑使用状态模式呢?当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为,就可以使用状态模式。另外,如果业务需求某项业务有多个状态,通常都是一些枚举常量,状态的变化都是依靠大量的分支判断语句来实现,此时应该考虑将每一种业务状态定义为一个State子类,这样这些对象就可以不依赖于其他对象而独立变化了,如果某天客户需求改了,增加或减少业务状态或改变状态流程,都不是困难了。
改进版本2.0——状态模式
from abc import ABCMeta, abstractmethod
class State():
__metaclass__ = ABCMeta
@abstractmethod
def write_program(self, work):
pass
class ForenoonState(State):
def write_program(self, work):
if work.hour < 12:
print("当前时间: {} 点, 上午工作,精神百倍".format(work.hour))
else:
work.set_state(NoonState())
work.write_program()
class NoonState(State):
def write_program(self, work):
if work.hour < 13:
print("当前时间: {} 点, 饿了,午饭,犯困,午休".format(work.hour))
else:
work.set_state(AfternoonState())
work.write_program()
class AfternoonState(State):
def write_program(self, work):
if work.hour < 17:
print("当前时间: {} 点, 下午状态还可以,继续努力".format(work.hour))
else:
work.set_state(EveningState())
work.write_program()
class EveningState(State):
def write_program(self, work):
if work.task_finished == True:
work.set_state(RestState())
work.write_program()
elif work.hour < 21:
print("当前时间: {} 点, 加班中,好累".format(work.hour))
else:
work.set_state(SleepingState())
work.write_program()
class SleepingState(State):
def write_program(self, work):
print("当前时间: {} 点, 不行了,睡着了".format(work.hour))
class RestState(State):
def write_program(self, work):
print("当前时间: {} 点, 收工,下班".format(work.hour))
class Work():
def __init__(self, state):
self.state = state
self.hour = 0
self.task_finished = False
def set_state(self, state):
self.state = state
def write_program(self):
self.state.write_program(self) # 精髓
work = Work(ForenoonState())
work.hour = 9
work.write_program()
work.hour = 10
work.write_program()
work.hour = 12
work.write_program()
work.hour = 13
work.write_program()
work.hour = 14
work.write_program()
work.hour = 17
work.work_finished = True
# work_finished = False
work.write_program()
work.hour = 19
work.write_program()
work.hour = 22
work.write_program()
当前时间: 9 点, 上午工作,精神百倍
当前时间: 10 点, 上午工作,精神百倍
当前时间: 12 点, 饿了,午饭,犯困,午休
当前时间: 13 点, 下午状态还可以,继续努力
当前时间: 14 点, 下午状态还可以,继续努力
当前时间: 17 点, 加班中,好累
当前时间: 19 点, 加班中,好累
当前时间: 22 点, 不行了,睡着了
点评
假如老板规定“员工必须在20点之前离开公司”,那么只需要增加一个“强制下班状态”,然后改动一下“傍晚工作状态”就可以了。而这是不影响其他状态的代码的。
[Python设计模式] 第16章 上班,干活,下班,加班——状态模式的更多相关文章
- [Python设计模式] 第22章 手机型号&软件版本——桥接模式
github地址:https://github.com/cheesezh/python_design_patterns 紧耦合程序演化 题目1 编程模拟以下情景,有一个N品牌手机,在上边玩一个小游戏. ...
- [Python设计模式] 第25章 联合国维护世界和平——中介者模式
github地址:https://github.com/cheesezh/python_design_patterns 题目背景 联合国在世界上就是中介者的角色,各国之间的关系复杂,类似不同的对象和对 ...
- [Python设计模式] 第23章 烤串的哲学——命令模式
github地址:https://github.com/cheesezh/python_design_patterns 题目1 用程序模拟,顾客直接向烤串师傅提需求. class Barbecuer( ...
- [Python设计模式] 第12章 基金理财更省事——外观模式
github地址:https://github.com/cheesezh/python_design_patterns 题目1 用程序模拟股民直接炒股的代码,比如股民投资了股票1,股票2,股票3,国债 ...
- [Python设计模式] 第10章 怎么出试卷?——模版方法模式
github地址:https://github.com/cheesezh/python_design_patterns 题目 小时候数学老师的随堂测验,都是老师在黑板上写题目,学生在下边抄,然后再做题 ...
- [Python设计模式] 第2章 商场收银软件——策略模式
github地址: https://github.com/cheesezh/python_design_patterns 题目 设计一个控制台程序, 模拟商场收银软件,根据客户购买商品的单价和数量,计 ...
- 《Think Python》第16章学习笔记
目录 <Think Python>第16章学习笔记 16.1 Time 16.2 纯函数(Pure functions) 16.3 修改器(Modifiers) 16.4 原型 vs. 方 ...
- [Python设计模式] 第1章 计算器——简单工厂模式
github地址:https://github.com/cheesezh/python_design_patterns 写在前面的话 """ 读书的时候上过<设计模 ...
- [Python设计模式] 第21章 计划生育——单例模式
github地址:https://github.com/cheesezh/python_design_patterns 单例模式 单例模式(Singleton Pattern)是一种常用的软件设计模式 ...
随机推荐
- js获取元素提示信息
js获取元素提示信息 var date=$("#date").attr('placeholder'); js修改元素的提示信息 $("#date").attr( ...
- day11 装饰器---函数的使用方法
这个是一个难点,以后面试会经常出现的,要搞懂! 装饰器升级版,进阶内容1: def outer(flag): def wrapper(func): def inner(*args,**kwargs): ...
- String.IsNullorEmpty()方法的使用
!= null 就是不为null !string.IsNullOrEmpty 不是null且不是""(string.Empty)
- CentOS 7开机出现welcome to emergency mode! 解决方法
CentOS7.3昨天用的还好好的的,但是今天开机提示如下(如图提示):welcome to emergency mode!after logging in ,type “journalctl -xb ...
- NSL:CPK_NN神经网络实现预测哪个样本与哪个样本处在同一层,从而科学规避我国煤矿突水灾难—Jason niu
load water_data.mat attributes = mapminmax(attributes); P_train = attributes(:,1:35); T_train = clas ...
- lvs dr 模型配置详解
前期准备: 两台服务器 note01(lvs服务器) note02(real sever) 1 首先在note01配置子网卡: ifconfig eth0: :2意思是eth0的子接口,随便一个数字就 ...
- 004.Heartbeat+HAProxy+MySQL半复制高可用架构
一 基础环境 节点 系统版本 MySQL版本 业务IP 心跳IP Master CentOS 7.5 MySQL 5.6 192.168.88.100 192.168.77.100 Slave Cen ...
- 浅析js闭包
闭包是一个老生常谈的问题,简单概括下闭包的形成的两个条件: 1.定义在函数内部 2.函数内部引用父层作用域变量 举一个最简单的例子: function test() { var a = 1; func ...
- JavaIO流中的拷贝
JavaIO流中对数据的操作尤为重要,掌握了基本的拷贝操作,才能将各种数据源的操作联系起来. 先来看看对文件夹的拷贝吧: /** * 利用递归实现文件夹的拷贝操作 * 分析:判断 * 是文件:调用拷贝 ...
- 负载均衡---ribbon
Ribbon:提供云端负载均衡,有多种负载均衡策略可供选择,可配合服务发现和断路器使用. 上一篇简单讲解了eureka的使用,这一篇文章基于上一篇的基础上,讲一下springcloud的另一个重要的组 ...