基于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()
相关推荐
打工仔折腾 AI6 小时前
从零写一个CAD 05:以鼠标为中心的滚轮缩放矩阵顺序不能反
后端·python·线性代数·性能优化·矩阵·计算机外设·ai agent 实战
计算机毕业编程指导师7 小时前
【计算机毕设选题】基于Hadoop+Spark的化妆品销售数据分析与可视化系统源码 毕业设计 选题推荐 毕设选题 数据分析 机器学习
大数据·hadoop·python·计算机·spark·课程设计·化妆品
泡海椒7 小时前
JQuick-Excel 导入反向映射实战:让中文表头稳定落到业务字段
开发语言·python·excel
欣欣之王来了7 小时前
前端开发学习路线图:2026年Vue方向最新版
前端·学习·架构·项目·vue3教程
wdfk_prog7 小时前
LWIP教程 00:从网线上的电信号到 lwIP——PHY、MAC、DMA 与 `netif` 的完整边界
运维·网络·笔记·学习·ip
泡茶喝茶写代码7 小时前
A股量化数据工程:从 REST 接口到策略信号(第 7 篇):盈利能力因子:毛利率、净利率与 ROE
java·python·股票数据api·股票数据api接口·股票api数据接口·股票量化数据api·股票量化数据接口
朝朝辞暮i7 小时前
VLA 系统学习第 2 课:Behavior Cloning——机器人究竟怎么从示范中学动作?
人工智能·python·vla
znx9397 小时前
手动交易 VS 量化交易:孰优孰劣?深度对比
人工智能·python·机器学习·期魔方
for_ever_love__7 小时前
概率与统计——分布、期望与贝叶斯,语言模型的建模基础
python·机器学习·大模型·概率论
ss2737 小时前
AI全栈实战 | 3.5-01 Python 全栈前端最小集:不会 React 也能做出能看的后台,关键就一条线
前端·python·react.js