一.概述

策略模式 定义了算法族,分别封装起来,让他们可以互相替换,此模式让算法的变化独立于使用算法的客户。

策略模式的三要素:

抽象策略角色: 策略类,通常由一个接口或者抽象类实现。

具体策略角色:包装了相关的算法和行为。

环境角色:持有一个策略类的引用,最终给客户端调用。

二.案例驱动

提出问题:要求做出一套模拟鸭子的游戏,游戏中会出现各种鸭子,它们一边游泳,一边呱呱叫。

分析:根据OO设计思想,无非就是使各种鸭子实现自己相应的功能即可,如鸭子游泳,鸭子呱呱叫。

解决方案1.0:设计一个接口(Duck),然后根据需要完成不同的实现,如红头鸭,绿头鸭。。。。

public interface Duck {
    public abstract void quack();
    public abstract void swim();
    public abstract void display();
}
public MallardDuck implements Duck{
    public abstract void quack(){
        System.out.println("呱呱~~");
    }
    public abstract void swim(){
        System.out.println("欢快的游泳~~");
    }
    public abstract void display(){
        System.out.println("绿头鸭~~");
    }
}
public RedHeadDuck implements Duck{
    public abstract void quack(){
        System.out.println("呱呱~~");
    }
    public abstract void swim(){
        System.out.println("欢快的游泳~~");
    }
    public abstract void display(){
        System.out.println("红头鸭~~");
    }
}

突然增加一个新的需求,要求有野鸭,除了具有这两个功能外,还会飞(fly),同时还有一种橡皮鸭,叫声时吱吱。。

此时该方案便暴露了一下缺点。。。。

缺点:牵一发而动全身,我们很难知道所有鸭子的行为,当针对有些实现需要添加新的功能时

解决方案1.1

为了更加灵活,面向接口编程。

public interface Flyable {
    public abstract void fly();
}
public interface Swimable {
    public abstract void swim();
}
public interface Quackable {
    public abstract void quack();
}
public RedHeadDuck implements Quackable implements Swimable {...}
public WildDuck implements Quackable implements Swimable implements Flyable {...}

如果有一万种鸭子,这种方式简直不敢想象,重复代码太多!

解决方案2.0

采用策咯模式解决此问题。

step1:把会变化的部分取出来,并封装起来,好让其他代码不受影响。

step2:封装行为的大局观

step3:代码实现

抽象策略角色

// 飞行行为
public interface FlyBehavior {
    public abstract void fly();
}
// 叫声行为
public interface QuackBehavior {
    public abstract void quack();
}

具体策略对象

// 橡皮鸭叫
public RubberDuckBehavior implements QuackBehavior {
    public abstract void quack(){
        System.out.println("吱吱~~");
    }
}
// 野鸭叫
public WildDuckBehavior implements QuackBehavior {
    public abstract void quack(){
        System.out.println("嘎嘎~~");
    }
}
// 大黄鸭叫
public YellowDuckBehavior implements QuackBehavior {
    public abstract void quack(){
        System.out.println("呱呱~~");
    }
}
// 不会飞
public FlyNoWay implements FlyBehavior {
    public abstract void fly(){
        System.out.println("不会飞~~");
    }
}
// 用翅膀飞
public FlyWithWings implements FlyBehavior {
    public abstract void fly(){
        System.out.println("用翅膀飞~~");
    }
}
// 螺旋桨飞
public FlyLikePlane implements FlyBehavior {
    public abstract void fly(){
        System.out.println("用螺旋桨~~");
    }
}

环境角色

抽象类

public abstract class Duck {
     FlyBehavior flyBehavior;
     QuackBehavior quackBehavior;
    // 动态设定行为
    public void setFlyBehavior(FlyBehavior flyBehavior) {
        this.flyBehavior = flyBehavior;
    }
    public void setQuackBehavior(QuackBehavior quackBehavior) {
        this.quackBehavior = quackBehavior;
    }
    public void performFly() {
        flyBehavior.fly();
    }
    public void performQuack() {
        quackBehavior.quack();
    }
    public abstract display() {}
    public void swim() {
        System.out.println("鸭子天生会游泳!");
    }
}

实现

public class WildDuck implements Duck {
     FlyBehavior flyBehavior;
     QuackBehavior quackBehavior;
    public WildDuck() {
        // 默认会飞,野鸭叫嘎嘎
        this.flyBehavior = new FlyWithWings();
        this.quackBehavior = new WildDuckBehavior();
    }
    // 动态设定行为
    public void setFlyBehavior(FlyBehavior flyBehavior) {
        this.flyBehavior = flyBehavior;
    }
    public void setQuackBehavior(QuackBehavior quackBehavior) {
        this.quackBehavior = quackBehavior;
    }
    public void performFly() {
        flyBehavior.fly();
    }
    public void performQuack() {
        quackBehavior.quack();
    }
    public abstract display() {
        System.out.println("这是一只野鸭!");
    }
    public void swim() {
        System.out.println("鸭子天生会游泳!");
    }
}

需求改变:野鸭的翅膀受伤,不会飞了

    public static void main(String[] args) {
        Duck duck = new WildDuck();
        duck.setFlyBehavior(new FlyNoWay());
        duck.performFly();// 输出:不会飞~~
    }

需改改变:新增一只火箭鸭,能飞到太空,不会游泳,外形像火箭一样,叫嘎嘎

public RocketDuckFlyBehavior implements FlyBehavior {
    public abstract void fly(){
        System.out.println("飞到太空~~");
    }
}
public class RocketDuck implements Duck {
     FlyBehavior flyBehavior;
     QuackBehavior quackBehavior;
    public WildDuck() {
        // 默认会飞,野鸭叫嘎嘎
        this.flyBehavior = new RocketDuckFlyBehavior();
        this.quackBehavior = new WildDuckQuackBehavior();
    }
    // 动态设定行为
    public void setFlyBehavior(FlyBehavior flyBehavior) {
        this.flyBehavior = flyBehavior;
    }
    public void setQuackBehavior(QuackBehavior quackBehavior) {
        this.quackBehavior = quackBehavior;
    }
    public void performFly() {
        flyBehavior.fly();
    }
    public void performQuack() {
        quackBehavior.quack();
    }
    public abstract display() {
        System.out.println("外形像火箭~~");
    }
    public void swim() {
        System.out.println("不会游泳");
    }
}

三.策略模式的优缺点

优点:

1.策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族。恰当使用继承可以把代码转移到符类,从而避免重复代码 。

2.在策略模式中利用组合和委托来让环境角色拥有执行算法的能力,这也是继承的一种更轻便的替代方案。

3.提供了对开放—封闭原则的完美支持,将算法封装在独立的strategy中,使得它们易于切换,易于理解,易于扩展

4.利用组合、委托和多态等技术和思想,可以有效地避免多重条件选择语句

缺点:

 1.客户端必须知道所有的策略类,区分他们之间的区别,并自行决定使用哪一个策略类。

 2.针对每一种行为情况需要创建一个策略类,造成很多的策略类。

设计模式:HelloWorld之策略模式的更多相关文章

  1. 【转】设计模式 ( 十八 ) 策略模式Strategy(对象行为型)

    设计模式 ( 十八 ) 策略模式Strategy(对象行为型) 1.概述 在软件开发中也常常遇到类似的情况,实现某一个功能有多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成 ...

  2. 设计模式 ( 十八 ) 策略模式Strategy(对象行为型)

    设计模式 ( 十八 ) 策略模式Strategy(对象行为型) 1.概述 在软件开发中也经常遇到类似的情况,实现某一个功能有多种算法或者策略,我们能够依据环境或者条件的不同选择不同的算法或者策略来完毕 ...

  3. 《Head First 设计模式》[01] 策略模式

    <Head First 设计模式>(点击查看详情) 1.写在前面的话 之前在列书单的时候,看网友对于设计模式的推荐里说,设计模式的书类别都大同小异,于是自己就选择了Head First系列 ...

  4. javascript设计模式--策略模式

    javascript策略模式总结 1.什么是策略模式? 策略模式的定义是:定义一系列的算法,把他们独立封装起来,并且可以相互替换. 例如我们需要写一段代码来计算员工的奖金.当绩效为a时,奖金为工资的5 ...

  5. [head first 设计模式] 第一章 策略模式

    [head first 设计模式] 第一章 策略模式 让我们先从一个简单的鸭子模拟器开始讲起. 假设有个简单的鸭子模拟器,游戏中会出现各种鸭子,此系统的原始设计如下,设计了一个鸭子超类,并让各种鸭子继 ...

  6. Python设计模式: 最佳的"策略"模式实践代码

    Python设计模式: 最佳的"策略"模式实践代码 今天抽空看了下流畅的python,发现里面介绍了不少python自带的库的使用实例,用起来非常的优雅. 平时用Python来写爬 ...

  7. [设计模式] javascript 之 策略模式

    策略模式说明 定义: 封装一系列的算法,使得他们之间可以相互替换,本模式使用算法独立于使用它的客户的变化. 说明:策略模式,是一种组织算法的模式,核心不在于算法,而在于组织一系列的算法,并且如何去使用 ...

  8. 设计模式:Strategy 策略模式 -- 行为型

    设计模式 策略模式Strategy(对象行为型) 这是几年前写的文字(转载做的笔记更准确些),发觉还是废话多了点. 其实,核心就是5.结构中的UML图 5.1 和 5.2(新增).现在看这张图就觉得一 ...

  9. 设计模式浅谈----策略模式(c#及java实现)

    一.何为策略模式 策略模式是行为型模式的一种,主要用于需要使用不同的算法来处理不同的数据对象时使用,是一种可以在运行时选择算法的设计模式.也称为政策模式. 主要解决:在有多种算法相似的情况下,使用 i ...

随机推荐

  1. 使用 Angular CLI 和 Webpack 分析包尺寸

    使用 Angular CLI 和 Webpack 分析包尺寸 对于 Web app 来说,高性能总是最高优先级,对于 Angular 也不例外.但是随着应用复杂度的不断增长,我们如何才能知道哪些内容打 ...

  2. 【iOS】 含tableView的ViewController基类的实现

    上篇博客写了ViewController的基类的实现,这篇博客主要写在BaseViewController的基础上实现一个含tableView控件的基类的实现,主要给包含tableView的页面来继承 ...

  3. python开发:python基本数据类型

    运算符 1.算数运算: 2.比较运算: 3.赋值运算: 4.逻辑运算: 5.成员运算: 基本数据类型 1.数字 int(整型) 在32位机器上,整数的位数为32位,取值范围为-2**31-2**31- ...

  4. Asp.Net Core 2.0 项目实战(8)Core下缓存操作、序列化操作、JSON操作等Helper集合类

    本文目录 1.  前沿 2.CacheHelper基于Microsoft.Extensions.Caching.Memory封装 3.XmlHelper快速操作xml文档 4.Serializatio ...

  5. Android学习——NDK交叉编译

    原创作品,转载请注明出处,严禁非法转载.如有错误,请留言! email:40879506@qq.com 一. 环境1.GNU/Linux Ubuntu12.04操作系统(x86) 二. 下载NDK安装 ...

  6. JDK1.8源码(七)——java.util.HashMap 类

    本篇博客我们来介绍在 JDK1.8 中 HashMap 的源码实现,这也是最常用的一个集合.但是在介绍 HashMap 之前,我们先介绍什么是 Hash表. 1.哈希表 Hash表也称为散列表,也有直 ...

  7. pandas(七)数据规整化:清理、转换、合并、重塑之合并数据集

    pandas对象中的数据可以通过一些内置的方式进行合并: pandas.merge 可根据一个或多个键将不同的DataFrame中的行连接起来. pandas.concat可以沿着一条轴将多个对象堆叠 ...

  8. [python]_ELVE_pip2和pip3如何共存

    作者:匿名用户链接:https://www.zhihu.com/question/21653286/answer/95532074来源:知乎著作权归作者所有,转载请联系作者获得授权. 想学习Pytho ...

  9. Spring-cloud(二)注册服务提供者搭建

    上文已经写了如何去搭建注册中心,仅有注册中心是远远不够的,所以我们需要注册到注册中心并提供服务的节点,这里称为注册服务提供者 前提 阅读上文,并成功搭建注册中心,环境无需改变 项目搭建 这里我们需要新 ...

  10. 关于myeclipse启动报错:An internal error has occurred. java.lang.NullPointerException解决办法

    启动myeclipse报错,百度了一下网友处理方式,对比日志,发现现在已有的教程真的是巨人坑: 如果出现了上述的错误按照如下的3个步骤解决:1.首先关闭MyEclipse工作空间.2.然后删除工作空间 ...