《人人都懂设计模式》-监听模式

最近在撸这本书,

作个记录。

from abc import ABCMeta, abstractmethod
# 引入ABCMeta和abstractmethod来定义抽象类和抽象方法
import time

"""

# version 1.0
class WaterHeater:
    # 热水器, 战胜寒冬的有利武器

    def __init__(self):
        self.__observers = []
        self.__temperature = 25

    def get_temperature(self):
        return self.__temperature

    def set_temperature(self, temperature):
        self.__temperature = temperature
        print("当前温度是:" + str(self.__temperature) + " C")
        self.notifies()

    def notifies(self):
        for o in self.__observers:
            o.update(self)

    def add_observer(self, observer):
        self.__observers.append(observer)


class Observer(metaclass=ABCMeta):
    # 洗澡模式和饮用模式的父类

    @abstractmethod
    def update(self, water_heater):
        pass


class WashingMode(Observer):
    # 该模式用于洗澡

    def update(self, water_heater):
        if 50 <= water_heater.get_temperature() < 70:
            print("水已烧好,温度正好,可以来洗澡了。")


class DrinkingMod(Observer):
    # 该模式用于饮用
    def update(self, water_heater):
        if water_heater.get_temperature() >= 100:
            print("水已烧开,可以来饮用了。")
"""


# version 2.0
class Observable:
    # 被观察者的基类

    def __init__(self):
        self.__observers = []

    def add_observer(self, observer):
        self.__observers.append(observer)

    def remove_observer(self, observer):
        self.__observers.remove(observer)

    def notify_observers(self, observer=0):
        for o in self.__observers:
            o.update(self, observer)


class WaterHeater(Observable):
    # 热水器, 战胜寒冬的有利武器

    def __init__(self):
        super().__init__()
        self.__temperature = 25

    def get_temperature(self):
        return self.__temperature

    def set_temperature(self, temperature):
        self.__temperature = temperature
        print("当前温度是:" + str(self.__temperature) + " C")
        self.notify_observers()


class Observer(metaclass=ABCMeta):
    # 观察者的基类

    @abstractmethod
    def update(self, observable, observer):
        pass


class WashingMode(Observer):
    # 该模式用于洗澡

    def update(self, observable, observer):
        if isinstance(observable, WaterHeater) and 50 <= observable.get_temperature() < 70:
            print("水已烧好,温度正好,可以来洗澡了。")


class DrinkingMod(Observer):
    # 该模式用于饮用
    def update(self, observable, observer):
        if isinstance(observable, WaterHeater) and observable.get_temperature() >= 100:
            print("水已烧开,可以来饮用了。")


def test_water_heater():
    heater = WaterHeater()
    washing_observer = WashingMode()
    drinking_observer = DrinkingMod()
    heater.add_observer(washing_observer)
    heater.add_observer(drinking_observer)
    heater.set_temperature(20)
    heater.set_temperature(40)
    heater.set_temperature(60)
    heater.set_temperature(80)
    heater.set_temperature(100)


test_water_heater()


# 实践应用:登陆异常的检测与提醒
class Account(Observable):

    def __init__(self):
        super().__init__()
        self.__latest_ip = {}
        self.__latest_region = {}

    def __get_region(self, ip):
        ip_regions = {
            '101.47.18.9': '浙江省杭州市',
            '67.218.147.69': '美国洛彬矶'
        }
        region = ip_regions.get(ip)
        return '' if region is None else region

    def __is_long_distance(self, name, region):
        latest_region = self.__latest_region.get(name)
        return latest_region is not None and latest_region != region

    def login(self, name, ip, login_time):
        region = self.__get_region(ip)
        if self.__is_long_distance(name, region):
            self.notify_observers({'name': name, 'ip': ip, 'region': region, 'time': login_time})
        self.__latest_region[name] = region
        self.__latest_ip[name] = ip


class SmsSender(Observer):
    def update(self, observable, observer):
        print("[短信发送] {} 您好,检测到您的帐户可能登陆异常,最近一次登陆信息:\n 登陆地区:{} 登陆ip: {} 登陆时间:{}"
              .format(observer["name"], observer["region"], observer["ip"], observer["time"]))


class MailSender(Observer):
    def update(self, observable, observer):
        print("[邮件发送] {} 您好,检测到您的帐户可能登陆异常,最近一次登陆信息:\n 登陆地区:{} 登陆ip: {} 登陆时间:{}"
              .format(observer["name"], observer["region"], observer["ip"], observer["time"]))


def test_login():
    account = Account()
    account.add_observer(SmsSender())
    account.add_observer(MailSender())
    account.login("Tony", '101.47.18.9', time.time())
    account.login("Tony", '67.218.147.69', time.time())
    account.login("Tony", '101.47.18.9', time.time())


test_login()
C:\Python36\python.exe C:/Users/Sahara/PycharmProjects/test/python_search.py
当前温度是:20 C
当前温度是:40 C
当前温度是:60 C
水已烧好,温度正好,可以来洗澡了。
当前温度是:80 C
当前温度是:100 C
水已烧开,可以来饮用了。
[短信发送] Tony 您好,检测到您的帐户可能登陆异常,最近一次登陆信息:
 登陆地区:美国洛彬矶 登陆ip: 67.218.147.69 登陆时间:1565402412.372697
[邮件发送] Tony 您好,检测到您的帐户可能登陆异常,最近一次登陆信息:
 登陆地区:美国洛彬矶 登陆ip: 67.218.147.69 登陆时间:1565402412.372697
[短信发送] Tony 您好,检测到您的帐户可能登陆异常,最近一次登陆信息:
 登陆地区:浙江省杭州市 登陆ip: 101.47.18.9 登陆时间:1565402412.372697
[邮件发送] Tony 您好,检测到您的帐户可能登陆异常,最近一次登陆信息:
 登陆地区:浙江省杭州市 登陆ip: 101.47.18.9 登陆时间:1565402412.372697

Process finished with exit code 0

猜你喜欢

转载自www.cnblogs.com/aguncn/p/11330652.html
今日推荐