基于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()
相关推荐
学测绘的小杨11 小时前
CompassFusion:一个从 GNSS 到 GNSS/INS 组合导航的独立工程包
python
zzzzzz31017 小时前
当产品经理说这个很简单:我用Python自动化处理奇葩需求的实战指南
python·pycharm·产品经理
雪隐18 小时前
个人电脑玩AI-06让5060 Ti给你打工——不光能画画,Qwen3-TTS还能学人说话,连我老板都信了!
人工智能·后端·python
兵慌码乱1 天前
面向桌面端的资产管理系统分层架构设计与核心模块实现
python·系统架构·sqlite·pyqt5·数据库设计·桌面应用开发·mvc架构
咖啡八杯1 天前
GoF设计模式——策略模式
java·后端·spring·设计模式
hboot1 天前
AI工程师第三课 - 机器学习基础
python·scikit-learn·kaggle
顾林海1 天前
Agent入门阶段-编程基础-Python:流程控制
python·agent·ai编程
呱呱复呱呱2 天前
Django CBV 源码解读:一个请求是怎么找到你的 get() 方法的
python·django
曲幽2 天前
刚部署的 LibreTranslate 频频翻车?我掏出了 20 年前的 StarDict 词典,用 FastAPI 搭了个本地词典翻译 API
python·fastapi·web·translate·goldendict·libretranslate·stardict·pystardict