美文网首页Android精选
设计模式(一)之策略模式

设计模式(一)之策略模式

作者: 探索的影子 | 来源:发表于2019-01-19 18:00 被阅读28次

问题场景
现在我们设计好了以下类


image.png

超类鸭子,不同的鸭子外观是不一样的,所以展示的方法是抽象的方法。不同种类的鸭子都继承duck,并重写展示方法。

需求-----鸭子是可以飞的

有一天项目经理说:“鸭子是可以飞的”。那么这个时候,你也许会直接想到要不直接在超类里面写一个fly的方法。这样所有继承的鸭子都可以实现fly的方法。
貌似这样好像没有什么问题,这样所有的子类都可以实现飞翔。


image.png

bug---塑料鸭子在天上飞

随着项目的进行,项目里面需要创建一个塑料鸭子的类,根据我们的oo设计原则,我们应该继承duck类。这样就会有个问题
塑料鸭子也具备了天上飞的方法,想想是不是有点毛骨悚然。所有继承的问题就出现了:虽然很多时候,继承都能够完成代码的复用,但是破坏了封装,不是所有的鸭子都是可以飞翔的。继承是不能够采用了。

改进---实现接口

这时候,你肯定会想到既然继承不行,那我就实现接口。写一个flyable接口,每一个可以飞的鸭子类我实现它这样的话,就可以解决塑料鸭子在天上飞的问题了。

问题---代码复用度不够

虽然解决了塑料鸭子在天上飞的问题,但是有一个隐藏的问题:复用度不够,代码反复写。这里只有两种鸭子,但是如果有二十多种鸭子呢?难道我们要写二十多次?聪明的程序员都是会偷懒的。那么有没有种简单的方式,解决这种问题呢?

解决---成员变量实现

划重点
设计原则

找出应用中可能变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。

在这里飞行是变化的部分,不是所有的鸭子都是可以飞翔的。所以我们需要将这个行为提取出来,组建成一个新的类来代表飞行的行为。


image.png

我不清楚这样的uml表达是否是准确的所以我也贴上代码:

抽象父类duck
package com.yyh.StrategyPattern;

/**
 * 抽象父类
 */
public abstract class Duck {
    private FlyBehavior flyBehavior;
    public void swimming(){
        System.out.println("duck.swimming");
    }

    public void quack(){
        System.out.println("duck.quack");
    }

    public abstract void display();

    public FlyBehavior getFlyBehavior() {
        return flyBehavior;
    }

    public void setFlyBehavior(FlyBehavior flyBehavior) {
        this.flyBehavior = flyBehavior;
    }
}

MallardDuck
package com.yyh.StrategyPattern;

public class MallardDuck extends Duck {
    private FlyBehavior flyBehavior;
    @Override
    public void display(){
        System.out.println("MallardDuck.绿头");
    }
}

RedheadDuck
package com.yyh.StrategyPattern;

public class RedheadDuck extends Duck {
    private FlyBehavior flyBehavior;
    @Override
    public void display(){
        System.out.println("RedheadDuck.红头");
    }
}


RubberDuck
package com.yyh.StrategyPattern;

public class RubberDuck extends Duck {

    @Override
    public void display(){
        System.out.println("RedheadDuck.塑料的");
    }


}

FlyBehavior
package com.yyh.StrategyPattern;

public interface FlyBehavior {

    void fly();
}


FlyWithWings
package com.yyh.StrategyPattern;

public class FlyWithWings implements FlyBehavior {
    @Override
    public void fly() {
        System.out.println("通过翅膀飞行");
    }
}


FlyNoWay
package com.yyh.StrategyPattern;

public class FlyNoWay implements FlyBehavior {
    @Override
    public void fly() {
        System.out.println("原地蹦跶了一下");
    }
}

测试类
package com.yyh.StrategyPattern;

public class TestMain {
    public static void main(String[] args) {
        Duck mallardDuck = new MallardDuck();
        mallardDuck.setFlyBehavior(new FlyWithWings());
        Duck redheadDuck = new RedheadDuck();
        redheadDuck.setFlyBehavior(new FlyWithWings());
        Duck rubberDuck = new RubberDuck();
        rubberDuck.setFlyBehavior(new FlyNoWay());
        System.out.println("mallardDuck:");
        mallardDuck.getFlyBehavior().fly();
        System.out.println("redheadDuck:");
        redheadDuck.getFlyBehavior().fly();
        System.out.println("rubberDuck:");
        rubberDuck.getFlyBehavior().fly();
    }
}

测试结果

image.png

分析

这样的话,我们没有删除曾经的业务逻辑,只是添加了一个成员变量就解决了不同鸭子的飞行问题。并且通过set方式的话,可以在程序运行的时候,动态改变行为。

动态改变行为

如果我们在运行的过程中,给红头鸭子一个火箭,让它坐火箭飞行呢?其实我们就只需要写一个新的飞的实现类就可以了。在程序指定的位置set一下,就可以改变鸭子的行为了,

FlyWithRocket
package com.yyh.StrategyPattern;

public class FlyWithRocket implements FlyBehavior {
    @Override
    public void fly() {
        System.out.println("坐火箭,惊了~~");
    }
}

新的测试类
package com.yyh.StrategyPattern;

public class TestMain {
    public static void main(String[] args) {
        Duck mallardDuck = new MallardDuck();
        mallardDuck.setFlyBehavior(new FlyWithWings());
        Duck redheadDuck = new RedheadDuck();
        redheadDuck.setFlyBehavior(new FlyWithWings());
        Duck rubberDuck = new RubberDuck();
        rubberDuck.setFlyBehavior(new FlyNoWay());
        System.out.println("mallardDuck:");
        mallardDuck.getFlyBehavior().fly();
        System.out.println("redheadDuck:");
        redheadDuck.getFlyBehavior().fly();
        System.out.println("rubberDuck:");
        rubberDuck.getFlyBehavior().fly();
        System.out.println("==动态修改状态====:");
        //坐火箭上天
        redheadDuck.setFlyBehavior(new FlyWithRocket());
        System.out.println("redheadDuck:");
        redheadDuck.getFlyBehavior().fly();
    }
}

测试结果


image.png

笔记

设计原则

少用继承,多用组合

策略模式定义

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

喜欢和评论是我更新和学习的最大动力,谢谢!

相关文章

  • 简说设计模式之策略模式

    前言:对于设计模式基础概念可以去看[简说设计模式之设计模式概述] 一、什么是策略模式 策略(Strategy)模式...

  • PHP设计模式之策略模式

    PHP设计模式之策略模式

  • PHP设计模式之策略模式

    PHP设计模式之策略模式

  • 策略模式 2018-11-04

    设计模式之策略模式 官方说明设计模式的3个角色: 环境角色:context , 持有一个策略的引用 抽象策略角色,...

  • 策略模式

    参考资料:漫话:如何给女朋友解释什么是策略模式? 设计模式之策略模式(实例+Demo) Java设计模式(8)——...

  • 学习Head First设计模式Day1

    Java设计模式之设计模式 策略模式:策略模式定义了算法簇,分别封装起来,让他们之间可以互相替换,此设计模式让算法...

  • Java设计模式——策略模式

    Java设计模式之策略模式 这期分享的模式是策略模式是程序设计中最常用的了,因为开发工作中总是会使用到策略模式。 ...

  • 策略模式

    本文参考自: 《JAVA设计模式》之策略模式(Strategy) 1. 作用 策略模式属于对象的行为模式。其用意是...

  • 设计模式之策略模式

    设计模式之策略模式 一 策略模式定义 策略模式在百度百科中的解释是: 策略模式是指对一系列的算法定义,并将每一个算...

  • Java设计模式之策略模式

    Java设计模式之策略模式 简介 在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行...

网友评论

    本文标题:设计模式(一)之策略模式

    本文链接:https://www.haomeiwen.com/subject/hebadqtx.html