基于Python学习《Head First设计模式》 第一章 策略模式

抽象超类Animal

python 复制代码
from abc import ABC, abstractmethod

# 方式一
# class Animal:
#
#     def make_sound(self):
#         raise NotImplementedError('子类必须实现make_sound方法')

# 方式二
class Animal(ABC):
    """抽象类"""

    @abstractmethod
    def make_sound(self):
        """子类必须实现该方法,表示所有动物都能发出声音"""
        pass


class Dog(Animal):

    def make_sound(self):
        self._bark()

    def _bark(self):  # 单下划线表示仅内部调用,相当于java的private
        print("汪汪叫")


class Cat(Animal):

    def make_sound(self):
        self._meow()

    def _meow(self):
        print("喵喵叫")


if __name__ == '__main__':
    dog = Dog()
    dog.make_sound()

    cat = Cat()
    cat.make_sound()

实现鸭子的行为

python 复制代码
from abc import ABC, abstractmethod


class FlyBehavior:

    def fly(self):
        raise NotImplementedError

class FlyWithWings(FlyBehavior):

    def fly(self):
        print("鸭子飞行")

class FlyNoWay(FlyBehavior):

    def fly(self):
        print('不会飞')



class QuackBehavior(ABC):

    @abstractmethod
    def quack(self):
        pass

class Quack(QuackBehavior):

    def quack(self):
        print('鸭子呱呱叫')

class Squeak(QuackBehavior):

    def quack(self):
        print('橡皮鸭子呱呱叫')

class MuteQuack(QuackBehavior):

    def quack(self):
        print('不会叫')

鸭子类

python 复制代码
class Duck:

    def __init__(self):
        self.fly_behavior = None
        self.quack_behavior = None

    def perform_fly(self):
        if self.fly_behavior:
            self.fly_behavior.fly()

    def perform_quack(self):
        if self.quack_behavior:
            self.quack_behavior.quack()

    def swim(self):
        pass

    @abstractmethod
    def display(self):
        pass

整合鸭子的行为

python 复制代码
class MallardDuck(Duck):

    def __init__(self):
        super().__init__()
        self.fly_behavior = FlyWithWings()
        self.quack_behavior = Quack()

    def display(self):
        print("I'm a real Mallard Duck")

测试Duck

python 复制代码
if __name__ == '__main__':
    mallard = MallardDuck()
    mallard.perform_quack()
    mallard.perform_fly()

动态设定行为

python 复制代码
class Duck:
	...

    def set_fly_behavior(self, fly_behavior: FlyBehavior):
        self.fly_behavior = fly_behavior

    def set_quack_behavior(self, quack_behavior: QuackBehavior):
        self.quack_behavior = quack_behavior

class ModelDuck(Duck):

    def __init__(self):
        super().__init__()
        self.fly_behavior = FlyNoWay()
        self.quack_behavior = Quack()

    def display(self):
        print("I'm a model duck")

class FlyRocketPowered(FlyBehavior):
    """利用火箭动力的飞行行为"""

    def fly(self):
        print("I'm flying with a rocket!")

if __name__ == '__main__':

    model = ModelDuck()
    model.perform_fly()
    model.set_fly_behavior(FlyRocketPowered())
    model.perform_fly()

或者换一种方式设置属性,效果一样

python 复制代码
class Duck:

    def __init__(self):
        self._fly_behavior = None
        self._quack_behavior = None

	...

    @property
    def fly_behavior(self):
        return self._fly_behavior

    @fly_behavior.setter
    def fly_behavior(self, fly_behavior: FlyBehavior):
        self._fly_behavior = fly_behavior


    @property
    def quack_behavior(self):
        return self._quack_behavior

    @quack_behavior.setter
    def quack_behavior(self, quack_behavior: QuackBehavior):
        self._quack_behavior = quack_behavior


if __name__ == '__main__':
    model = ModelDuck()
    model.perform_fly()
    model.fly_behavior = FlyRocketPowered()
    # model.set_fly_behavior(FlyRocketPowered())
    model.perform_fly()

完整代码

python 复制代码
from abc import ABC, abstractmethod
from typing import Optional


class FlyBehavior:
    """飞行行为"""

    def fly(self):
        raise NotImplementedError


class FlyWithWings(FlyBehavior):
    """用翅膀飞行"""

    def fly(self):
        print("I'm flying!!")


class FlyNoWay(FlyBehavior):
    """不支持飞行"""

    def fly(self):
        print("I can't fly")


class QuackBehavior(ABC):
    """发出声音行为"""

    @abstractmethod
    def quack(self):
        pass


class Quack(QuackBehavior):

    def quack(self):
        print('鸭子呱呱叫')


class Squeak(QuackBehavior):

    def quack(self):
        print('橡皮鸭子呱呱叫')


class MuteQuack(QuackBehavior):

    def quack(self):
        print('不会叫')


class Duck:

    def __init__(self,
                 fly_behavior: Optional[FlyBehavior] = None,
                 quack_behavior: Optional[QuackBehavior] = None
                 ):
        self._fly_behavior = fly_behavior
        self._quack_behavior = quack_behavior

    def perform_fly(self):
        if self.fly_behavior:
            self.fly_behavior.fly()

    def perform_quack(self):
        if self.quack_behavior:
            self.quack_behavior.quack()

    def swim(self):
        pass

    @abstractmethod
    def display(self):
        pass

    # def set_fly_behavior(self, fly_behavior: FlyBehavior):
    #     self.fly_behavior = fly_behavior
    #
    # def set_quack_behavior(self, quack_behavior: QuackBehavior):
    #     self.quack_behavior = quack_behavior

    @property
    def fly_behavior(self):
        return self._fly_behavior

    @fly_behavior.setter
    def fly_behavior(self, fly_behavior: FlyBehavior):
        self._fly_behavior = fly_behavior


    @property
    def quack_behavior(self):
        return self._quack_behavior

    @quack_behavior.setter
    def quack_behavior(self, quack_behavior: QuackBehavior):
        self._quack_behavior = quack_behavior

class MallardDuck(Duck): # 继承,属于鸭子 IS-A,是一种鸭子的子类型

    def __init__(self):
        super().__init__()
        self.fly_behavior = FlyWithWings() # 组合,拥有飞行行为 HAS-A
        self.quack_behavior = Quack() # 组合,拥有发出声音行为 HAS-A

    def display(self):
        print("I'm a real Mallard Duck")


class ModelDuck(Duck):

    def __init__(self):
        super().__init__()
        self.fly_behavior = FlyNoWay()
        self.quack_behavior = Quack()

    def display(self):
        print("I'm a model duck")


class FlyRocketPowered(FlyBehavior):
    """利用火箭动力的飞行行为"""

    def fly(self):
        print("I'm flying with a rocket!")


if __name__ == '__main__':
    mallard = MallardDuck()
    mallard.perform_quack()
    mallard.perform_fly()

    model = ModelDuck()
    model.perform_fly()
    model.fly_behavior = FlyRocketPowered()
    # model.set_fly_behavior(FlyRocketPowered())
    model.perform_fly()

总结

练习题

python 复制代码
from abc import abstractmethod


class WeaponBehavior:
    """武器行为"""

    @abstractmethod
    def use_weapon(self):
        """使用武器"""
        pass


class KnifeBehavior(WeaponBehavior):
    def use_weapon(self):
        return '匕首'


class BowAndArrowBehavior(WeaponBehavior):
    def use_weapon(self):
        return '弓箭'


class AxeBehavior(WeaponBehavior):
    def use_weapon(self):
        return '斧头'


class SwordBehavior(WeaponBehavior):
    def use_weapon(self):
        return '宝剑'


class Character:
    """人物"""

    def __init__(self, w: WeaponBehavior = None):
        self._weapon = w

    @property
    def weapon(self):
        return self._weapon

    @weapon.setter
    def weapon(self, w: WeaponBehavior):
        self._weapon = w

    def fight(self):
        """战斗"""
        if self._weapon is None:
            print(f"{self.__class__.__name__} has no weapon!")
            return

        weapon = self._weapon.use_weapon()
        print(f"{self.__class__.__name__} use {weapon} fight")

    @abstractmethod
    def display(self) -> None:
        pass

class Queen(Character):
    def display(self) -> None:
        print("I'm a Queen")


class King(Character):
    def display(self) -> None:
        print("I'm a King")


class Troll(Character):
    def display(self) -> None:
        print("I'm a Troll")


class Knight(Character):
    def display(self) -> None:
        print("I'm a Knight")


if __name__ == '__main__':
    queen = Queen()
    queen.fight()
    queen.weapon = KnifeBehavior()
    queen.fight()

    king = King(KnifeBehavior())
    king.fight()

    king.weapon = BowAndArrowBehavior()
    king.fight()
相关推荐
孟健7 小时前
Karpathy 用 200 行纯 Python 从零实现 GPT:代码逐行解析
python
静水流深_沧海一粟8 小时前
04 | 别再写几十个参数的构造函数了——建造者模式
设计模式
StarkCoder8 小时前
从UIKit到SwiftUI的迁移感悟:数据驱动的革命
设计模式
码路飞8 小时前
写了个 AI 聊天页面,被 5 种流式格式折腾了一整天 😭
javascript·python
曲幽11 小时前
FastAPI压力测试实战:Locust模拟真实用户并发及优化建议
python·fastapi·web·locust·asyncio·test·uvicorn·workers
敏编程15 小时前
一天一个Python库:jsonschema - JSON 数据验证利器
python
前端付豪15 小时前
LangChain记忆:通过Memory记住上次的对话细节
人工智能·python·langchain
阿星AI工作室16 小时前
给openclaw龙虾造了间像素办公室!实时看它写代码、摸鱼、修bug、写日报,太可爱了吧!
前端·人工智能·设计模式
databook16 小时前
ManimCE v0.20.1 发布:LaTeX 渲染修复与动画稳定性提升
python·动效
花酒锄作田1 天前
使用 pkgutil 实现动态插件系统
python