大话设计模型 Task05 状态、适配、单例

一、状态模式

问题描述

假设我们要描述一名员工一天不同时间的工作状态,正常来看是比较简单的,直接从早上上班开始,根据一些时间变化切换到其他状态。但假设我们切换到一个状态后又可能需要根据另外的条件再次切换,比如本来在写代码,到晚上了还没写完,继续写。好不容易写完了,需要切换到下班状态;或者没写完,直到睡着还没写完。这需要各种条件判断(每个状态都要判断是否满足跳到其他状态),不光是写起来复杂,新增状态和更新状态更是会变得异常麻烦。

此时,很自然我们就会想要将一个个状态独立出来,为每个状态设置所有需要的切换条件,在状态发生变化时改变对应的行为。这样我们只需要关心状态从 A 转换到 B,而不用管各种判断逻辑。

问题分析

状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。

模式定义

状态模式(State),当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
在这里插入图片描述

代码实现

# 工作状态
class State(object):
    def write_program(self,w):
        pass

# 睡眠状态
class SleepingState(State):
    def write_program(self, w):
        print(f"当前时间:{w.hour}点 不行了,睡着了。")

# 下班休息状态
class RestState(State):
    def write_program(self, w):
        print(f"当前时间:{w.hour}点 下班回家了")

# 晚间工作状态
class EveningState(State):
    def write_program(self, w):
        if w.taskFinished:
            w.set_state(RestState())
            w.write_program()
        else:
            if w.hour < 21:
                print(f"当前时间:{w.hour}点 加班哦,疲累之极")
            else:
                w.set_state(SleepingState())
                w.write_program()

# 下午工作状态
class AfternoonState(State):
    def write_program(self, w):
        if w.hour < 17:
            print(f"当前时间:{w.hour}点 下午状态还不错,继续努力")
        else:
            w.set_state(EveningState())
            w.write_program()

# 中午工作状态
class NoonState(State):
    def write_program(self, w):
        if w.hour < 13:
            print(f"当前时间:{w.hour}点 饿了,午饭;犯困,午休。")
        else:
            w.set_state(AfternoonState())
            w.write_program()

# 上午工作状态
class ForenoonState(State):
    def write_program(self, w):
        if w.hour < 12:
            print(f"当前时间:{w.hour}点 上午工作,精神百倍")
        else:
            w.set_state(NoonState())
            w.write_program()

# 工作
class Work(object):
    __current = None
    __hour = None
    __finish = False
    def __init__(self):
        self.__current = ForenoonState()

    def set_state(self,s:State):
        self.__current = s
    def write_program(self):
        self.__current.write_program(self)

    def get_hour(self):
        return self.__hour
    def set_hour(self,hour):
        self.__hour = hour
    def get_finish(self):
        return self.__finish
    def set_finish(self,finish):
        self.__finish = finish
    hour = property(get_hour,set_hour)
    taskFinished = property(get_finish,set_finish)


if __name__ == '__main__':
    # 紧急项目
    emergencyProjects = Work()
    emergencyProjects.hour = 9
    emergencyProjects.write_program()
    emergencyProjects.hour = 10
    emergencyProjects.write_program()
    emergencyProjects.hour = 12
    emergencyProjects.write_program()
    emergencyProjects.hour = 13
    emergencyProjects.write_program()
    emergencyProjects.hour = 14
    emergencyProjects.write_program()
    emergencyProjects.hour = 17

    emergencyProjects.taskFinished = False

    emergencyProjects.write_program()
    emergencyProjects.hour = 19
    emergencyProjects.write_program()
    emergencyProjects.hour = 22
    emergencyProjects.write_program()

二、适配器模式

问题描述

想象我们要出国旅游,到了异国他乡不懂当地语言怎么办?路上卯足马力突击学习?当然可以!不过更简单的做法是,打开手机翻译软件,切换到「当地语言-中文」就可以借助它与当地人进行对话了。这样,只要我们手机里有其他语言与中文的互译,就可以走遍地球任意一个角落并和当地人沟通了,而且我们自己并不需要真正掌握任何一门外语。

当然,有时候用翻译软件有点麻烦,有不准确的情况。此时,可以在当地找一个翻译,比如领导人出访国外时会带一个翻译,刚去 NBA 打球的姚明也随时有一个翻译在身边。

问题分析

中文与其他语言的互译器以及翻译人员就是适配器,我们自己或姚明就是那个已有的满足功能的类,接口和环境就是异国他乡。

模式定义

适配器模式(Adapter),将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作

代码实现

# 球员
class Player(object):
    name = ""
    def __init__(self,name):
        self.name = name
    def attack(self):
        pass
    def defense(self):
        pass

# 前锋
class Forwards(Player):
    name = ""
    def __init__(self,name):
        self.name = name
    def attack(self):
        print(f"前锋 {self.name} 进攻")
    def defense(self):
        print(f"前锋 {self.name} 防守")

# 中锋
class Center(Player):
    name = ""
    def __init__(self,name):
        self.name = name
    def attack(self):
        print(f"中锋 {self.name} 进攻")
    def defense(self):
        print(f"中锋 {self.name} 防守")

# 后卫
class Guards(Player):
    name = ""
    def __init__(self,name):
        self.name = name
    def attack(self):
        print(f"后卫 {self.name} 进攻")
    def defense(self):
        print(f"后卫 {self.name} 防守")

# 外籍中锋
class ForeignCenter:
    __name = ""
    def __init__(self):
        pass
    def 进攻(self):
        print(f"外籍中锋 {self.name} 进攻")
    def 防守(self):
        print(f"外籍中锋 {self.name} 防守")

    def get_name(self):
        return self.__name
    def set_name(self,name):
        self.__name = name
    name = property(get_name,set_name)

# 翻译者
class Translator(Player):
    __wjzf = ForeignCenter()
    def __init__(self,name):
        self.__wjzf.name = name
    def attack(self):
        self.__wjzf.进攻()
    def defense(self):
        self.__wjzf.防守()

if __name__ == '__main__':
    b = Forwards("巴蒂尔")
    b.attack()
    m = Guards("麦克格雷迪")
    m.attack()

    ym = Translator("姚明")
    ym.attack()
    ym.defense()

三、单例模式

问题描述

一个类只能有一个实例在生活中是很常见的,比如打印机程序,政府部门。当我们创建这些类的实例时,我们希望每次创建后得到的都是同一个实例。很直观地,我们知道需要在构造函数上下功夫,当我们需要创建一个新的实例时,如果已经有了该类的实例,就直接返回,而不是新建一个。

问题分析

对一些只需要一个全局实例的情况,推荐使用单例模式。

模式定义

单例模式(Singleton),保证一个类仅有一个实例,并提供一个访问它的全局访问点。

通常我们可以让一个全局变量使得一个对象被访问,但它不能防止你实例化多个对象。一个最好的办法就是,让类自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问该实例的方法。

代码实现

import time
import threading

class Singleton(object):
    # 线程锁
    lock = threading.Lock()
    def __new__(cls,*args,**kwargs):
        # 双重锁定
        if not hasattr(cls,'_instance'):
            with cls.lock:
                if not hasattr(cls,'_instance'):
                    time.sleep(0.5)
                    orig = super(Singleton,cls)
                    cls._instance = orig.__new__(cls,*args,**kwargs)
        return cls._instance

def func():
        obj = Singleton()
        print(id(obj))

if __name__ == '__main__':
    a = Singleton()
    b = Singleton()
    if a == b:
        print("两个对象是相同的实例。")

    # 多线程测试
    for i in range(10):
        thread = threading.Thread(target=func)
        thread.start()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值