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章 上班,干活,下班,加班——状态模式的更多相关文章

  1. [Python设计模式] 第22章 手机型号&软件版本——桥接模式

    github地址:https://github.com/cheesezh/python_design_patterns 紧耦合程序演化 题目1 编程模拟以下情景,有一个N品牌手机,在上边玩一个小游戏. ...

  2. [Python设计模式] 第25章 联合国维护世界和平——中介者模式

    github地址:https://github.com/cheesezh/python_design_patterns 题目背景 联合国在世界上就是中介者的角色,各国之间的关系复杂,类似不同的对象和对 ...

  3. [Python设计模式] 第23章 烤串的哲学——命令模式

    github地址:https://github.com/cheesezh/python_design_patterns 题目1 用程序模拟,顾客直接向烤串师傅提需求. class Barbecuer( ...

  4. [Python设计模式] 第12章 基金理财更省事——外观模式

    github地址:https://github.com/cheesezh/python_design_patterns 题目1 用程序模拟股民直接炒股的代码,比如股民投资了股票1,股票2,股票3,国债 ...

  5. [Python设计模式] 第10章 怎么出试卷?——模版方法模式

    github地址:https://github.com/cheesezh/python_design_patterns 题目 小时候数学老师的随堂测验,都是老师在黑板上写题目,学生在下边抄,然后再做题 ...

  6. [Python设计模式] 第2章 商场收银软件——策略模式

    github地址: https://github.com/cheesezh/python_design_patterns 题目 设计一个控制台程序, 模拟商场收银软件,根据客户购买商品的单价和数量,计 ...

  7. 《Think Python》第16章学习笔记

    目录 <Think Python>第16章学习笔记 16.1 Time 16.2 纯函数(Pure functions) 16.3 修改器(Modifiers) 16.4 原型 vs. 方 ...

  8. [Python设计模式] 第1章 计算器——简单工厂模式

    github地址:https://github.com/cheesezh/python_design_patterns 写在前面的话 """ 读书的时候上过<设计模 ...

  9. [Python设计模式] 第21章 计划生育——单例模式

    github地址:https://github.com/cheesezh/python_design_patterns 单例模式 单例模式(Singleton Pattern)是一种常用的软件设计模式 ...

随机推荐

  1. JavaSE| 数组

    1.数组(array) 数组就是多个相同类型数据的组合,实现对这些数据的统一管理. 数组中的元素可以是任何数据类型,包括基本数据类型和引用数据类型.数组属引用类型,数组型数据是对象(object),每 ...

  2. 013 mysql中find_in_set()函数的使用

    在工作中遇见过,对于新知识,在这里写一写文档. 1.作用 举个例子,也许不理解,在看完后面的SQL示例,再来看就明白了: 有个文章表里面有个type字段,它存储的是文章类型,有 1头条.2推荐.3热点 ...

  3. MATLAB视频读取转换为图片

    转换mp4到jpg格式的图片: % convert .mp4 to jpg picture t='C:\Documents and Settings\luokh\桌面\Matlab编程\Matlab编 ...

  4. scrapy安装

    1.scrapy的安装 -前提,最好用virtualenv 创建的虚拟环境安装 -windows -官方推荐用anaconda -自定已安装 -1.https://www.lfd.uci.edu/~g ...

  5. Tp-validate进阶

    阶段1:基础 application/controller/v1/Banner.php <?php namespace app\api\controller\v1; use think\Cont ...

  6. supervisor 监控redis & mongodb

    安装 安装python brew install python 安装pipwget https://bootstrap.pypa.io/get-pip.pysudo python get-pip.py ...

  7. C语言实现链栈

    我自己写的代码部分: #include<stdio.h> #include<stdlib.h> #include<string.h> typedef struct ...

  8. 003.Ansible基础使用

    一 Ansible命令用法 Ansible命令行执行方式有:Ad-Hoc.Ansible-playbook两种,Web方式其官方提供付费产品Tower.Ad-Hoc主要用于临时命令的执行,Ansibl ...

  9. nginx: [error] open() "/var/run/nginx/nginx.pid" failed (2: No such file or directory)

    在重启nginx服务的时候,出现了这个错误. [root@izuf68g6a94fj32w0afx00z etc]# nginx -c /var/run/nginx/nginx.pid nginx: ...

  10. mysql主从配置和galera集群

    mariadb主从 主从多用于网站架构,因为主从的同步机制是异步的,数据的同步有一定延迟,也就是说有可能会造成数据的丢失,但是性能比较好,因此网站大多数用的是主从架构的数据库,读写分离必须基于主从架构 ...