文档章节

设计模式01策略模式

AllenOR灵感
 AllenOR灵感
发布于 2017/09/10 01:18
字数 2046
阅读 1
收藏 0

原始代码模型(全部采用继承)

代码
# -.- coding:utf-8 -.-
from __future__ import print_function


class Duck(object):

    def __init__(self, *args, **kwargs):
        self.name = '鸭子'
        self._ = '{}{}{}'

    def display(self):
        raise NotImplementedError

    def _display(self, value):
        value = self._.format(self.name, ': ', value)
        print(value)
        return value

    def quack(self):
        return self._display('呱呱叫')

    def swim(self):
        return self._display('游泳')


class MallardDuck(Duck):

    def __init__(self, *args, **kwargs):
        super(MallardDuck, self).__init__(*args, **kwargs)
        self.name = '绿头鸭'

    def display(self):
         return self._display('外观是绿头')


class RedheadDuck(Duck):

    def __init__(self, *args, **kwargs):
        super(RedheadDuck, self).__init__(*args, **kwargs)
        self.name = '红头鸭'

    def display(self):
        return self._display('外观是红头')


if __name__ == '__main__':
    mallard_duck = MallardDuck()
    mallard_duck.display()
    mallard_duck.quack()
    print()
    redhead_duck = RedheadDuck()
    redhead_duck.display()
    redhead_duck.quack()

# 显示结果
绿头鸭: 外观是绿头
绿头鸭: 呱呱叫

红头鸭: 外观是红头
红头鸭: 呱呱叫
需求

现在要求增加一个让鸭子飞的功能。(备注:需求要求很模糊)

解决办法

在Duck父类中增加一个fly方法,那么所有的子类都会拥有飞行行为(因为这就是继承)。

# -.- coding:utf-8 -.-
from __future__ import print_function


class Duck(object):

    # 在原来的基础上增加一个fly方法
    def fly(self):
        return self._display('飞行')



# 增加一个橡皮鸭对象
class RubberDuck(Duck):

    def __init__(self, *args, **kwargs):
        super(RubberDuck, self).__init__(*args, **kwargs)
        self.name = '橡皮鸭'

    def display(self):
        return self._display('外观是橡皮')


if __name__ == '__main__':
    mallard_duck = MallardDuck()
    mallard_duck.display()
    mallard_duck.quack()
    mallard_duck.fly()
    print()
    redhead_duck = RedheadDuck()
    redhead_duck.display()
    redhead_duck.quack()
    redhead_duck.fly()
    print()
    redhead_duck = RubberDuck()
    redhead_duck.display()
    redhead_duck.quack()
    redhead_duck.fly()

# 显示结果
绿头鸭: 外观是绿头
绿头鸭: 呱呱叫
绿头鸭: 飞行

红头鸭: 外观是红头
红头鸭: 呱呱叫
红头鸭: 飞行

橡皮鸭: 外观是橡皮鸭
橡皮鸭: 呱呱叫
橡皮鸭: 飞行
延伸出来的问题

单从功能上来讲,在父类中增加了一个fly方法,那么所有的子类都拥有了fly行为,这是没问题的。但是从业务逻辑的角度来讲,那么并非所有鸭子都能飞(一般像被驯化的家鸭是没有飞行能力了,野鸭一般都能飞,故事中的橡皮鸭不能飞而且叫的声音也不一样,不是呱呱叫而是吱吱叫)。

另外一种尝试

采用继承中的一种特性<覆盖/或者叫多态>来让橡皮鸭自己实现自己的功能。

# -.- coding:utf-8 -.-
from __future__ import print_function


class Duck(object):

    def __init__(self, *args, **kwargs):
        self.name = '鸭子'
        self._ = '{}{}{}'

    def display(self):
        raise NotImplementedError

    def _display(self, value):
        value = self._.format(self.name, ': ', value)
        print(value)
        return value

    def fly(self):
        return self._display('飞行')

    def quack(self):
        return self._display('呱呱叫')

    def swim(self):
        return self._display('游泳')


class MallardDuck(Duck):

    def __init__(self, *args, **kwargs):
        super(MallardDuck, self).__init__(*args, **kwargs)
        self.name = '绿头鸭'

    def display(self):
        return self._display('外观是绿头')


class RedheadDuck(Duck):

    def __init__(self, *args, **kwargs):
        super(RedheadDuck, self).__init__(*args, **kwargs)
        self.name = '红头鸭'

    def display(self):
        return self._display('外观是红头')


class RubberDuck(Duck):

    def __init__(self, *args, **kwargs):
        super(RubberDuck, self).__init__(*args, **kwargs)
        self.name = '橡皮鸭'

    # 覆盖Duck的quack方法
    def quack(self):
        return self._display('吱吱叫')

    # 覆盖Duck的fly方法
    def fly(self):
        return self._display('不能飞行')

    def display(self):
        return self._display('外观是橡皮')


# 增加诱饵鸭
class DecoyDuck(Duck):

    def __init__(self, *args, **kwargs):
        super(DecoyDuck, self).__init__(*args, **kwargs)
        self.name = '诱饵鸭'

    # 覆盖Duck的quack方法
    def quack(self):
        return self._display('不能叫')

    # 覆盖Duck的fly方法
    def fly(self):
        return self._display('不能飞')

    def display(self):
        return self._display('外观是诱饵')


# 增加模型鸭
class ModelDuck(Duck):

    def __init__(self, *args, **kwargs):
        super(ModelDuck, self).__init__(*args, **kwargs)
        self.name = '模型鸭'

    # 覆盖Duck的quack方法
    def quack(self):
        return self._display('不能叫')

    # 覆盖Duck的fly方法
    def fly(self):
        return self._display('不能飞')

    def display(self):
        return self._display('外观是模型')


if __name__ == '__main__':
    mallard_duck = MallardDuck()
    mallard_duck.display()
    mallard_duck.quack()
    mallard_duck.fly()
    print()
    redhead_duck = RedheadDuck()
    redhead_duck.display()
    redhead_duck.quack()
    redhead_duck.fly()
    print()
    rubber_duck = RubberDuck()
    rubber_duck.display()
    rubber_duck.quack()
    rubber_duck.fly()
    print()
    decoy_duck = DecoyDuck()
    decoy_duck.display()
    decoy_duck.quack()
    decoy_duck.fly()
    print()
    model_duck = ModelDuck()
    model_duck.display()
    model_duck.quack()
    model_duck.fly()

# 查看结果
绿头鸭: 外观是绿头
绿头鸭: 呱呱叫
绿头鸭: 飞行

红头鸭: 外观是红头
红头鸭: 呱呱叫
红头鸭: 飞行

橡皮鸭: 外观是橡皮
橡皮鸭: 吱吱叫
橡皮鸭: 不能飞行

诱饵鸭: 外观是诱饵
诱饵鸭: 不能叫
诱饵鸭: 不能飞

模型鸭: 外观是模型
模型鸭: 不能叫
模型鸭: 不能飞

组合+继承

嗯,上面这个尝试确实能解决橡皮鸭不能飞的问题(解决这个问题至少有三种办法:第一种是实现代码都完全在具体的方法中完成,这样就没办法做到代码的复用;第二种是在外部写好函数,相同功能要求的行为调用该函数,但是这种对代码的组织会存在一定的问题,随着项目的不断扩大而变得越来越不容易管理;第三种就是抽象成一个类将类似的实现进行一个合理的归纳。)。目前代码中是有五种鸭子,如果有200种鸭子,其中有15种跟橡皮鸭一样吱吱叫但是要能飞,另外40种跟橡皮鸭一样不能飞行但是要呱呱叫,这种情况该如何复用(每种鸭子类都跟橡皮鸭类一样自己去写一遍实现,我觉得这个坑太大了)?

像这种情况就是典型的行为分类,将<叫>和<飞>的行为剥离出来,然后根据不同的鸭子属性去给予它不同的能力(这种多重的能力在不同鸭子之间的搭配使用就叫做组合)。

代码
# -.- coding:utf-8 -.-
from __future__ import print_function


################################################################################
# Display                                                                      #
################################################################################
class Display(object):

    def __init__(self):
        self._ = '{}{}{}'

    def display(self, name, value):
        value = self._.format(name, ': ', value)
        print(value)
        return value

################################################################################
# Ducks                                                                        #
################################################################################
class Duck(object):

    _ = '{}{}{}'

    def __init__(self, *args, **kwargs):
        self.name = '鸭子'
        self.fly_behavior = None
        self.quack_behavior = None
        self._display = Display().display

    def display(self):
        raise NotImplementedError

    def fly(self):
        if self.fly_behavior:
            return self.fly_behavior.fly(self.name)
        return self._display(self.name, '飞行')

    def quack(self):
        if self.quack_behavior:
            return self.quack_behavior.quack(self.name)
        return self._display(self.name, '呱呱叫')

    def swim(self):
        return self._display(self.name, '游泳')

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

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


class MallardDuck(Duck):

    def __init__(self, *args, **kwargs):
        super(MallardDuck, self).__init__(*args, **kwargs)
        self.name = '绿头鸭'

    def display(self):
        return self._display(self.name, '外观是绿头')


class RedheadDuck(Duck):

    def __init__(self, *args, **kwargs):
        super(RedheadDuck, self).__init__(*args, **kwargs)
        self.name = '红头鸭'

    def display(self):
        return self._display(self.name, '外观是红头')


class RubberDuck(Duck):

    def __init__(self, *args, **kwargs):
        super(RubberDuck, self).__init__(*args, **kwargs)
        self.name = '橡皮鸭'

    def quack(self):
        return self._display(self.name, '吱吱叫')

    def fly(self):
        return self._display(self.name, '不能飞行')

    def display(self):
        return self._display(self.name, '外观是橡皮')


class DecoyDuck(Duck):

    def __init__(self, *args, **kwargs):
        super(DecoyDuck, self).__init__(*args, **kwargs)
        self.name = '诱饵鸭'

    def quack(self):
        return self._display(self.name, '不能叫')

    def fly(self):
        return self._display(self.name, '不能飞')

    def display(self):
        return self._display(self.name, '外观是诱饵')


class ModelDuck(Duck):

    def __init__(self, *args, **kwargs):
        super(ModelDuck, self).__init__(*args, **kwargs)
        self.name = '模型鸭'

    def quack(self):
        return self._display(self.name, '不能叫')

    def fly(self):
        return self._display(self.name, '不能飞')

    def display(self):
        return self._display(self.name, '外观是模型')


################################################################################
# Quack behaviors                                                              #
################################################################################
class QuackBehavior(object):

    def quack(self, *args, **kwargs):
        raise NotImplementedError


class Quack(QuackBehavior):

    def quack(self, name):
        return Display().display(name, "呱呱叫")


class MuteQuack(QuackBehavior):
    def quack(self, name):
        return Display().display(name, "不能叫")


class Squeak(QuackBehavior):
    def quack(self, name):
        return Display().display(name, "吱吱叫")


class FakeQuack(QuackBehavior):
    def quack(self, name):
        return Display().display(name, "假叫")


################################################################################
# Fly behaviors                                                                #
################################################################################
class FlyBehavior(object):
    def fly(self, *args, **kwargs):
        pass


class FlyWithWings(FlyBehavior):
    def fly(self, name):
        return Display().display(name, "飞行!")


class FlyNoWay(FlyBehavior):
    def fly(self, name):
        return Display().display(name, "不能飞!")


class FlyRocketPowered(FlyBehavior):
    def fly(self, name):
        return Display().display(name, "坐火箭飞!")


if __name__ == '__main__':
    mallard_duck = MallardDuck()
    mallard_duck.display()
    mallard_duck.quack()
    mallard_duck.fly()

    print()

    mallard_duck = MallardDuck()
    mallard_duck.display()
    mallard_duck.set_quack_behavior(FakeQuack())
    mallard_duck.set_fly_behavior(FlyRocketPowered())
    mallard_duck.quack()
    mallard_duck.fly()

# 显示结果
绿头鸭: 外观是绿头
绿头鸭: 呱呱叫
绿头鸭: 飞行

绿头鸭: 外观是绿头
绿头鸭: 假叫
绿头鸭: 坐火箭飞!
解决了什么问题

在最后__main__中可以看到,通过剥离出两个行为类之后,可以在运行时灵活通过给定不同类来影响它的最终结果。
这里面的一切都依赖于接口的一致性。

模式总结

策略模式强调的是将性质和行为相似的代码封装起来,让它们之间可以相互替换。

核心理念

在运行时选择操作(Choosing the operations at Runtime).

模式类型

行为模式

设计原则
  1. 找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。
  2. 针对接口编程,而不是针对实现编程。
  3. 多用组合,少用继承。

参考

本文转载自:http://www.jianshu.com/p/ecc0c24cfdb4

共有 人打赏支持
AllenOR灵感
粉丝 10
博文 2634
码字总数 82983
作品 0
程序员
javascript 设计模式之工厂(Factory)模式

工厂模式介绍 工厂模式是一个创建型的模式,主要就是创建对象。其中工厂模式又分为简单工厂模式和抽象工厂模式。简单工厂模式是通过工厂方法确定创建 对应类型的对象。抽象工厂模式是通过子类...

hlxiong
2014/04/14
0
0
java设计模式-- 单例模式

在很久之前,也就是在大二暑假的时候,那时候看马士兵的视频教程中有提到很多的设计模式。 java的设计模式大致可以分为3大类,23种设计模式。 其中,创建型模式有5种:单例模式、建造者模式、...

爱学习的逃课君
2014/11/27
0
0
代理模式(Proxy Pattern):动态代理 - 最易懂的设计模式解析

前言 今天我来全面总结开发中最常用的设计模式 - 代理模式中的动态代理模式 其他设计模式介绍 1分钟全面了解“设计模式” 单例模式(Singleton) - 最易懂的设计模式解析 简单工厂模式(Sim...

Carson_Ho
04/09
0
0
【设计模式笔记】(十六)- 代理模式

一、简述 代理模式(Proxy Pattern),为其他对象提供一个代理,并由代理对象控制原有对象的引用;也称为委托模式。 其实代理模式无论是在日常开发还是设计模式中,基本随处可见,中介者模式中...

MrTrying
06/24
0
0
JavaScript 中常见设计模式整理

开发中,我们或多或少地接触了设计模式,但是很多时候不知道自己使用了哪种设计模式或者说该使用何种设计模式。本文意在梳理常见设计模式的特点,从而对它们有比较清晰的认知。 JavaScript 中...

牧云云
05/18
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

[MicroPython]STM32F407开发板驱动OLED液晶屏

1.实验目的 1.学习在PC机系统中扩展简单I/O 接口的方法。 2.进一步学习编制数据输出程序的设计方法。 3.学习 F407 Micropython开发板控制OLED显示字符。 2.所需元器件 F407 Micropython开发板...

bodasisiter
33分钟前
0
0
php require和include 相对路径一个有趣的坑

以前总是被教育,不要使用相对路径,这样性能比较差,但是相对路径的问题不仅仅是性能哦,看下面这里例子 这是项目结构 .├── main.php├── t│ ├── t1.php│ └── t2.php└─...

anoty
34分钟前
17
0
x64技术之SSDT_Hook

测试环境: 虚拟机: Windows 7 64bit 过PG工具 驱动加载工具 PCHunter64 系统自带的计算器和任务管理器等 实现思路: 实际思路与win32的思路一样.都是替换SSDT表里边的函数地址.不过微软被搞怕...

simpower
35分钟前
0
0
TreeMap源码分析,看了都说好

一、简介 TreeMap最早出现在JDK 1.2中,是 Java 集合框架中比较重要一个的实现。TreeMap 底层基于红黑树实现,可保证在log(n)时间复杂度内完成 containsKey、get、put 和 remove 操作,效率很...

Java小铺
45分钟前
0
0
协变、逆变

概念 假设 A、B表示类型 ≤ 表示继承关系 f<⋅>表示类型转换 若A ≤ B,则 A是B的子类,B是A的超类 协变、逆变 什么是型变?型变(type variance)允许对类型进行子类型转换。 为了下面讲解先...

obaniu
51分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部