Python设计模式(二)

时间:2024-04-29 08:50:08

一、外观模式

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2024-04-28 10:10
# @Author  : Maple
# @File    : 09-外观模式.py


"""
外观模式是一种结构型设计模式,它提供了一个统一的接口来访问子系统中的一组接口,从而使子系统更容易使用。
外观模式通过定义一个高层接口,让子系统的使用更加简单化,同时也帮助客户程序和子系统之间解耦
"""


"""
案例1:简单的计算机启动过程
这个例子演示了如何使用外观模式来简化计算机的启动过程。通过外观类,我们封装了启动计算机时涉及的复杂交互。
"""

class CPU:
    def start(self):
        print("CPU is starting...")

class Memory:
    def load(self, position, data):
        print(f"Loading data into position {position}")

class HardDrive:
    def read(self, lba, size):
        print(f"Reading {size} bytes from LBA {lba}")

class ComputerFacade:
    def __init__(self):
        self.cpu = CPU()
        self.memory = Memory()
        self.hard_drive = HardDrive()

    def start_computer(self):
        self.cpu.start()
        self.memory.load(0, "Operating System")
        self.hard_drive.read(1024, 2048)


"""
案例2:家庭影院系统
在这个例子中,外观模式用于简化家庭影院的操作。有多个设备,如投影仪、DVD播放器、音响系统等,外观模式使得用户通过一个简单的接口来操作所有这些设备。
"""
class Projector:
    def on(self):
        print("Projector turned on")
    def off(self):
        print("Projector turned off")

class DVDPlayer:
    def on(self):
        print("DVD Player turned on")
    def play(self, movie):
        print(f"Playing '{movie}'")
    def off(self):
        print("DVD Player turned off")

class SoundSystem:
    def on(self):
        print("Sound system turned on")
    def set_volume(self, level):
        print(f"Volume set to {level}")
    def off(self):
        print("Sound system turned off")

class HomeTheaterFacade:
    def __init__(self):
        self.projector = Projector()
        self.dvd_player = DVDPlayer()
        self.sound_system = SoundSystem()

    def watch_movie(self, movie):
        print("Get ready to watch a movie...")
        self.projector.on()
        self.sound_system.on()
        self.sound_system.set_volume(7)
        self.dvd_player.on()
        self.dvd_player.play(movie)

    def end_movie(self):
        print("Shutting movie theater down...")
        self.projector.off()
        self.dvd_player.off()
        self.sound_system.off()

"""
案例3:金融服务接口
这个例子展示了如何使用外观模式来提供一个简化的接口,用于访问复杂的金融服务,如信用评估、贷款审批和客户账户管理
"""

class CreditRatingSystem:
    def evaluate_credit(self, customer_id):
        print(f"Evaluating credit for customer {customer_id}")
        return True

class LoanApprovalSystem:
    def approve_loan(self, customer_id):
        print(f"Approving loan for customer {customer_id}")
        return True

class CustomerAccount:
    def create_account(self, customer_id):
        print(f"Account created for customer {customer_id}")

class BankingFacade:
    def __init__(self):
        self.credit_system = CreditRatingSystem()
        self.loan_system = LoanApprovalSystem()
        self.account_system = CustomerAccount()

    def process_loan(self, customer_id):
        print("Processing loan for customer...")
        if self.credit_system.evaluate_credit(customer_id):
            if self.loan_system.approve_loan(customer_id):
                self.account_system.create_account(customer_id)
                print(f"Loan processing complete for customer {customer_id}")



if __name__ == '__main__':


    print('********1.简单的计算机启动过程 **************')
    computer = ComputerFacade()
    computer.start_computer()
    computer = ComputerFacade()
    """
    CPU is starting...
    Loading data into position 0
    Reading 2048 bytes from LBA 1024
    CPU is starting...
    Loading data into position 0
    Reading 2048 bytes from LBA 1024
    """
    computer.start_computer()

    print('*******2.家庭影院系统**************')
    home_theater = HomeTheaterFacade()

    """
    Get ready to watch a movie...
    Projector turned on
    Sound system turned on
    Volume set to 7
    DVD Player turned on
    Playing 'Inception'
    """
    home_theater.watch_movie("Inception")


    """
    Shutting movie theater down...
    Projector turned off
    DVD Player turned off
    Sound system turned off
    """
    home_theater.end_movie()

    print('*******3.金融服务接口**************')
    banking = BankingFacade()
    """
    Processing loan for customer...
    Evaluating credit for customer 123456
    Approving loan for customer 123456
    Account created for customer 123456
    Loan processing complete for customer 123456
    """
    banking.process_loan(123456)

二、责任链模式

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2024-04-28 10:28
# @Author  : Maple
# @File    : 10-责任链模式.py


"""
责任链模式是一种行为设计模式,允许多个对象处理请求,或者将这些对象连成一条链
请求从链的一端流动到另一端,直到被处理。这种模式非常适用于有多个可能的处理程序或处理步骤的情况。
"""


"""
案例1:日志记录器
这个例子中使用责任链模式来处理不同级别的日志消息。可以设置多个日志记录器处理不同级别的日志。
"""
class Logger:
    INFO = 1
    DEBUG = 2
    ERROR = 3

    def __init__(self, level):
        self.level = level
        self.next_logger = None

    def set_next_logger(self, next_logger):
        self.next_logger = next_logger

    def log_message(self, level, message):
        if self.level <= level:
            self.write(message)
        if self.next_logger is not None:
            self.next_logger.log_message(level, message)

    def write(self, message):
        raise NotImplementedError("This method should be overridden.")

class ConsoleLogger(Logger):
    def write(self, message):
        print(f"Standard Console::Logger: {message}")

class ErrorLogger(Logger):
    def write(self, message):
        print(f"Error Console::Logger: {message}")

class FileLogger(Logger):
    def write(self, message):
        print(f"File::Logger: {message}")


"""
案例2:购物车订单处理
这个例子中,责任链用于处理购物车中的订单,包括验证用户数据、库存检查、和支付处理。
"""

class Handler:
    def __init__(self):
        self.next_handler = None

    def set_next(self, handler):
        self.next_handler = handler

    def handle(self, request):
        if self.next_handler:
            return self.next_handler.handle(request)
        return None

class AuthenticationHandler(Handler):
    def handle(self, request):
        if request.get("authenticated", False):
            print("User authenticated.")
            super().handle(request)
        else:
            print("Authentication failed.")
            return False

class InventoryCheckHandler(Handler):
    def handle(self, request):
        if request.get("items_in_stock", True):
            print("Inventory checked and all items available.")
            super().handle(request)
        else:
            print("Some items are out of stock.")
            return False

class PaymentProcessingHandler(Handler):
    def handle(self, request):
        if request.get("payment_successful", True):
            print("Payment processed successfully.")
            super().handle(request)
        else:
            print("Payment failed.")
            return False

"""
案例3:项目权限管理
在这个复杂的示例中,责任链模式用于项目权限管理,处理多种权限请求,包括读取、写入和删除权限。
"""

class AccessControl:
    READ = 1
    WRITE = 2
    DELETE = 3

    def __init__(self, permission_level):
        self.permission_level = permission_level
        self.next_control = None

    def set_next(self, control):
        self.next_control = control

    def request_permission(self, request_level, request):
        if self.permission_level <= request_level:
            self.grant_permission(request)
        if self.next_control is not None:
            self.next_control.request_permission(request_level, request)

    def grant_permission(self, request):
        raise NotImplementedError("Subclass must implement this method.")

class ReadAccess(AccessControl):
    def grant_permission(self, request):
        print(f"Read permission granted for accessing: {request}")

class WriteAccess(AccessControl):
    def grant_permission(self, request):
        print(f"Write permission granted for modifying: {request}")

class DeleteAccess(AccessControl):
    def grant_permission(self, request):
        print(f"Delete permission granted for removing: {request}")





if __name__ == '__main__':

    print('*******1.日志记录器**********')
    error_logger = ErrorLogger(Logger.ERROR)
    file_logger = FileLogger(Logger.DEBUG)
    console_logger = ConsoleLogger(Logger.INFO)

    error_logger.set_next_logger(file_logger)
    file_logger.set_next_logger(console_logger)

    # 只会打印INFO级别的日志
    # Standard Console::Logger: This is an information.
    error_logger.log_message(Logger.INFO, "This is an information.")


    # 打印INFO和DEBUG级别的日志
    """
    File::Logger: This is a debug level information.
    Standard Console::Logger: This is a debug level information.
    """
    error_logger.log_message(Logger.DEBUG, "This is a debug level information.")

    # 会打印INFO,DEBUG和ERROR级别的日志
    """
    Error Console::Logger: This is an error information.
    File::Logger: This is an error information.
    Standard Console::Logger: This is an error information.
    """
    error_logger.log_message(Logger.ERROR, "This is an error information.")

    print('*******2.购物车订单处理**********')
    auth_handler = AuthenticationHandler()
    inventory_handler = InventoryCheckHandler()
    payment_handler = PaymentProcessingHandler()

    auth_handler.set_next(inventory_handler)
    inventory_handler.set_next(payment_handler)

    request = {"authenticated": True, "items_in_stock": True, "payment_successful": True}
    """
    User authenticated.
    Inventory checked and all items available.
    Payment processed successfully.
    """
    auth_handler.handle(request)

    print('*******3. 项目权限管理**********')
    read_access = ReadAccess(AccessControl.READ)
    write_access = WriteAccess(AccessControl.WRITE)
    delete_access = DeleteAccess(AccessControl.DELETE)

    read_access.set_next(write_access)
    write_access.set_next(delete_access)

    # 只有读权限
    # Read permission granted for accessing: Project Documentation
    read_access.request_permission(AccessControl.READ, "Project Documentation")

    # 拥有读写权限
    """
    Read permission granted for accessing: Project Code
    Write permission granted for modifying: Project Code"""
    read_access.request_permission(AccessControl.WRITE, "Project Code")

    # 拥有读写和删除权限
    """
    Read permission granted for accessing: Project Data
    Write permission granted for modifying: Project Data
    Delete permission granted for removing: Project Data
    """
    read_access.request_permission(AccessControl.DELETE, "Project Data")

三、策略模式

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2024-04-28 10:59
# @Author  : Maple
# @File    : 11-策略模式.py


"""
策略模式是一种行为设计模式,它定义了一系列算法,并将每个算法封装起来
使它们可以互换。这种模式让算法的变化独立于使用算法的客户。
"""

"""
案例1:简单排序策略
在这个例子中,我们使用策略模式来选择不同的排序策略(比如冒泡排序、选择排序等)。
"""

from typing import List

class SortStrategy:
    def sort(self, dataset: List[int]) -> List[int]:
        raise NotImplementedError

class BubbleSort(SortStrategy):
    def sort(self, dataset: List[int]) -> List[int]:
        data = dataset[:]
        n = len(data)
        for i in range(n):
            for j in range(0, n-i-1):
                if data[j] > data[j+1]:
                    data[j], data[j+1] = data[j+1], data[j]
        return data

class SelectionSort(SortStrategy):
    def sort(self, dataset: List[int]) -> List[int]:
        data = dataset[:]
        for i in range(len(data)):
            min_idx = i
            for j in range(i+1, len(data)):
                if data[min_idx] > data[j]:
                    min_idx = j
            data[i], data[min_idx] = data[min_idx], data[i]
        return data

class Context:
    def __init__(self, strategy: SortStrategy):
        self.strategy = strategy

    def set_strategy(self, strategy: SortStrategy):
        self.strategy = strategy

    def sort_data(self, data: List[int]) -> List[int]:
        return self.strategy.sort(data)

"""
案例2:交通路线规划策略
这个例子中,我们定义不同的交通策略,比如驾车、公交和骑自行车。
"""

class RouteStrategy:
    def build_route(self, start: str, end: str) -> str:
        raise NotImplementedError

class DrivingStrategy(RouteStrategy):
    def build_route(self, start: str, end: str) -> str:
        return f"Route from {start} to {end} by car."

class TransitStrategy(RouteStrategy):
    def build_route(self, start: str, end: str) -> str:
        return f"Route from {start} to {end} by transit."

class BikingStrategy(RouteStrategy):
    def build_route(self, start: str, end: str) -> str:
        return f"Route from {start} to {end} by bike."

class Navigator:
    def __init__(self, strategy: RouteStrategy):
        self.strategy = strategy

    def set_strategy(self, strategy: RouteStrategy):
        self.strategy = strategy

    def get_route(self, start: str, end: str) -> str:
        return self.strategy.build_route(start, end)


"""
案例3:营销策略
在这个复杂的例子中,我们使用策略模式来处理不同的营销策略,如节日促销、忠诚客户促销等
"""

class MarketingStrategy:
    def apply_promotion(self, sale_amount: float) -> float:
        raise NotImplementedError

class HolidayPromotion(MarketingStrategy):
    def apply_promotion(self, sale_amount: float) -> float:
        return sale_amount * 0.9  # 10% discount

class LoyaltyPromotion(MarketingStrategy):
    def apply_promotion(self, sale_amount: float) -> float:
        return sale_amount * 0.85  # 15% discount

class NoPromotion(MarketingStrategy):
    def apply_promotion(self, sale_amount: float) -> float:
        return sale_amount  # no discount

class SalesOrder:
    def __init__(self, strategy: MarketingStrategy):
        self.strategy = strategy

    def set_strategy(self, strategy: MarketingStrategy):
        self.strategy = strategy

    def finalize_order(self, sale_amount: float) -> float:
        return self.strategy.apply_promotion(sale_amount)




if __name__ == '__main__':


    print('*********1.简单排序策略**********')
    data = [22, 91, 15, 3, 45]
    context = Context(BubbleSort())
    print("Bubble Sort:", context.sort_data(data))
    context.set_strategy(SelectionSort())
    print("Selection Sort:", context.sort_data(data))

    print('*********2.交通路线规划策略**********')
    navigator = Navigator(DrivingStrategy())
    print(navigator.get_route("Home", "Office"))
    navigator.set_strategy(TransitStrategy())
    print(navigator.get_route("Home", "Office"))

    print('*********3.营销策略**********')
    order = SalesOrder(HolidayPromotion())
    print("Holiday Promotion:", order.finalize_order(100))
    order.set_strategy(LoyaltyPromotion())
    print("Loyalty Promotion:", order.finalize_order(100))

四、模版方法模式

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2024-04-28 11:06
# @Author  : Maple
# @File    : 12-模版方法模式.py

"""
模板方法模式是一种行为设计模式,它在父类中定义了一个算法的框架,允许子类在不改变算法结构的前提下重写算法的特定步骤
这种模式特别适用于有多个步骤的过程,其中某些步骤的实现可能会随着上下文的变化而变化。
"""

"""
案例1:制作饮料
在这个简单的例子中,我们定义了一个制作饮料的过程,其中包括烧水、冲泡、倒入杯中和加调料这几个步骤
不同的饮料(如茶和咖啡)可以有不同的冲泡和调料添加方法。
"""

from abc import ABC, abstractmethod

class BeverageRecipe(ABC):
    def prepare(self):  # 模板方法
        self.boil_water()
        self.brew()
        self.pour_in_cup()
        self.add_condiments()

    def boil_water(self):
        print("Boiling water")

    @abstractmethod
    def brew(self):
        pass

    def pour_in_cup(self):
        print("Pouring into cup")

    @abstractmethod
    def add_condiments(self):
        pass

class Tea(BeverageRecipe):
    def brew(self):
        print("Steeping the tea")

    def add_condiments(self):
        print("Adding lemon")

class Coffee(BeverageRecipe):
    def brew(self):
        print("Dripping coffee through filter")

    def add_condiments(self):
        print("Adding sugar and milk")


"""
案例2:数据挖掘模型训练
这个例子中, 我们使用模板方法模式来定义一个数据挖掘模型训练的过程,包括数据预处理、模型训练和结果评估的步骤
允许不同类型的模型有不同的实现细节。
"""
class DataMining(ABC):
    def train_model(self):
        self.load_data()
        self.preprocess_data()
        self.fit_model()
        self.evaluate_model()

    def load_data(self):
        print("Loading data from database")

    @abstractmethod
    def preprocess_data(self):
        pass

    @abstractmethod
    def fit_model(self):
        pass

    def evaluate_model(self):
        print("Evaluating model performance")

class DecisionTreeModel(DataMining):
    def preprocess_data(self):
        print("Preprocessing data for Decision Tree")

    def fit_model(self):
        print("Fitting Decision Tree model")

class NeuralNetworkModel(DataMining):
    def preprocess_data(self):
        print("Normalizing data for Neural Network")

    def fit_model(self):
        print("Training Neural Network model")


if __name__ == '__main__':

    print('****1. 制作饮料******')
    tea = Tea()
    tea.prepare()

    coffee = Coffee()
    coffee.prepare()

    print('****2. 数据挖掘模型训练******')
    decision_tree = DecisionTreeModel()
    decision_tree.train_model()

    neural_network = NeuralNetworkModel()
    neural_network.train_model()

五、访问者模式

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2024-04-28 20:16
# @Author  : Maple
# @File    : 13-访问者模式.py
from abc import ABC, abstractmethod


"""
假设我们的系统已经有了 Keyboard 和 Monitor 类,且初期设计未考虑访问者模式
 --引入访问者模式首先需要添加一个 accept 方法到每个类
 --之后无论何时需要对键盘和显示器执行新的操作,我们只需创建实现了visit方法的新访问者类,而无需再次修改Keyboard或Monitor类。
 
"""

# 定义一个抽象的计算机组件
class ComputerPart(ABC):
    @abstractmethod
    def accept(self, computer_part_visitor):
        pass

# 定义一个具体的计算机组件-键盘
class Keyboard(ComputerPart):
    def accept(self, computer_part_visitor):
        computer_part_visitor.visit(self)

# 定义一个具体的计算机组件-显示器
class Monitor(ComputerPart):
    def accept(self, computer_part_visitor):
        computer_part_visitor.visit(self)


# 定义一个抽象的访问者
class ComputerPartVisitor(ABC):
    @abstractmethod
    def visit(self, element):
        pass

# 定义一个具体的访问者
class ComputerPartDisplayVisitor(ComputerPartVisitor):
    def visit(self, element):
        print(f"Displaying {element.__class__.__name__}.")

if __name__ == '__main__':

    print('*******1.访问者模式*********')
    # 1-1. 实例化2个电脑组件
    keyboard = Keyboard()
    monitor = Monitor()
    # 1-2. 实例化一个访问者
    visitor = ComputerPartDisplayVisitor()

    # 1-3. 电脑组件接受访问者,从而调用访问者中定义的visit方法
    #      实现电脑组件本身功能地扩展
    keyboard.accept(visitor)
    monitor.accept(visitor)

六、状态模式

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2024-04-28 20:26
# @Author  : Maple
# @File    : 14-状态模式.py
from abc import ABC, abstractmethod


"""
状态模式允许一个对象在其内部状态改变时改变它的行为
这个模式将每种状态的行为封装到对应的类中
"""

class State(ABC):
    @abstractmethod
    def handle(self, context):
        pass

class StartState(State):
    def handle(self, context):
        print("Player is in start state")
        context.state = self

class StopState(State):
    def handle(self, context):
        print("Player is in stop state")
        context.state = self


class Context:
    state = None

    def __init__(self):
        self.state = None

    def set_state(self, state):
        self.state = state

    def get_state(self):
        return self.state

"""
案例1: 工作流或业务流程管理
在工作流或业务流程管理中,特定文档(如报销单、请假条、工单等)可能有多个状态(如已创建、待审核、已批准、已拒绝)
状态模式可以用来管理状态之间的转换,以及在不同状态下的行为(如发送通知、修改数据库记录等)
"""

class DocumentState(ABC):
    def approve(self, document):
        pass

    def reject(self, document):
        pass

class Draft(DocumentState):
    def approve(self, document):
        document.state = PendingReview()
        print("Document moved to Pending Review")

class PendingReview(DocumentState):
    def approve(self, document):
        document.state = Approved()
        print("Document approved")
    def reject(self, document):
        document.state = Rejected()
        print("Document rejected")

class Approved(DocumentState):
    pass

class Rejected(DocumentState):
    pass

class Document:
    def __init__(self):
        self.state = Draft()

    def approve(self):
        self.state.approve(self)

    def reject(self):
        self.state.reject(self)


"""
案例2: 游戏角色的不同状态
在游戏开发中,角色可能有多种状态,如正常、加速、缓慢、无敌等,每种状态下角色的行为不同
状态模式允许角色对象在状态改变时seamlessly切换行为
"""

class CharacterState(ABC):
    def handle_input(self, character, input):
        pass

class NormalState(CharacterState):
    def handle_input(self, character, input):
        if input == "POWER_UP":
            print('进入加速状态')
            character.state = PoweredUpState()

class PoweredUpState(CharacterState):
    def handle_input(self, character, input):
        if input == "TIME_OUT":
            print('进入普通状态')
            character.state = NormalState()

class Character:
    def __init__(self):
        self.state = NormalState()

    def handle_input(self, input):
        self.state.handle_input(self, input)


"""
案例3: 网络连接的不同状态
网络连接通常具有多个状态,如未连接、正在连接、已连接、连接失败等
状态模式可以帮助管理这些状态及其在不同状态下的行为,如重试、断开、重置等
"""
class ConnectionState(ABC):
    def connect(self, connection):
        pass

class Disconnected(ConnectionState):
    def connect(self, connection):
        print("Attempting to connect...")
        connection.state = Connecting()

class Connecting(ConnectionState):
    def connect(self, connection):
        print("Connection successful")
        connection.state = Connected()

class Connected(ConnectionState):
    def disconnect(self, connection):
        print("Disconnected")
        connection.state = Disconnected()

class Connection:
    def __init__(self):
        self.state = Disconnected()

    def connect(self):
        self.state.connect(self)

    def disconnect(self):
        self.state.disconnect(self)








if __name__ == '__main__':

    print('******1. 状态模式入门*************')
    context = Context()
    start_state = StartState()
    stop_state = StopState()

    # context.state的状态设置为 start_state
    start_state.handle(context)
    print(context.get_state()) # <__main__.StartState object at 0x0000016616393D00>,其为StartState的一个实例

    stop_state.handle(context)
    print(context.get_state()) # <__main__.StopState object at 0x0000016616393CD0>,其为stop_state的一个实例


    print('******案例1: 工作流或业务流程管理*************')
    doc = Document()
    doc.approve()  # Moves to Pending Review
    doc.approve()  # Moves to Approved,执行完毕之后document的state变成Approved

    # 此时再执行reject,因为Approved类中定义的内容为pass,所以以下语句并不会有任何动作
    doc.reject()  # No effect, already approved
    """
    Output:
     -Document moved to Pending Review
     -Document approved
    """

    print('******案例2: 游戏角色的不同状态*************')
    hero = Character()
    hero.handle_input("POWER_UP")  # 进入加速状态
    hero.handle_input("TIME_OUT")  # 进入普通状态

    print('******案例3: 网络连接的不同状态*************')
    network = Connection()
    network.connect()  # Attempting to connect...
    network.connect()  # Connection successful
    network.disconnect()  # Disconnected

七、享元模式

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2024-04-28 20:53
# @Author  : Maple
# @File    : 15-享元模式.py

"""
享元模式主要用于性能优化,尤其是在处理大量小粒度对象的时候。它通过共享尽可能多的相似对象来减少内存使用。
"""

class Circle:
    def __init__(self, color):
        self.color = color

    def set_position(self, x, y):
        self.x = x
        self.y = y

    def draw(self):
        print(f"Drawing a {self.color} circle at ({self.x}, {self.y})")

class CircleFactory:
    _circles = {}

    @staticmethod
    def get_circle(color):
        if color not in CircleFactory._circles:
            CircleFactory._circles[color] = Circle(color)
        return CircleFactory._circles[color]

if __name__ == '__main__':


    circle1 = CircleFactory.get_circle("Red")
    circle1.set_position(100, 100)
    circle1.draw()

    circle2 = CircleFactory.get_circle("Red")
    circle2.set_position(200, 200)
    circle2.draw()

    # circle1和circle2是同一个对象
    print(circle1 is circle2) # True

八、命令模式

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2024-04-28 20:55
# @Author  : Maple
# @File    : 16-命令模式.py

"""
命令模式将一个请求封装为一个对象,从而让你使用不同的请求、队列或日志请求来参数化其他对象。命令模式也支持可撤销的操作。
"""
from abc import ABC, abstractmethod


class Light:
    def on(self):
        print("Light is on")

    def off(self):
        print("Light is off")

class Command(ABC):
    @abstractmethod
    def execute(self):
        pass

class LightOnCommand(Command):
    def __init__(self, light):
        self.light = light

    def execute(self):
        self.light.on()

class LightOffCommand(Command):
    def __init__(self, light):
        self.light = light

    def execute(self):
        self.light.off()

class RemoteControl:
    def __init__(self):
        self.command = None

    def set_command(self, command):
        self.command = command

    def press_button(self):
        self.command.execute()

if __name__ == '__main__':

    light = Light()
    on_command = LightOnCommand(light)
    off_command = LightOffCommand(light)
    remote = RemoteControl()

    remote.set_command(on_command)
    remote.press_button()

    remote.set_command(off_command)
    remote.press_button()