栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【设计模式】策略模式

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【设计模式】策略模式

文章目录
  • 一、背景
  • 二、工具箱的工具(本章)
    • 1、OO基础
    • 2、OO原则
    • 3、OO模式
  • 三、例子展示
    • 1、初期的鸭子系统
      • a.UML图
    • 2、中期的鸭子系统
      • a.UML图
    • 3、最终的鸭子系统
      • a.UML图
      • b.如何设计?
      • c.模式
  • 三、代码
    • 1. Duck相关
      • a.Duck
      • b.Duck子类
    • 2、行为相关
      • a.Fly
      • b.Quack
    • 3、测试Demo

一、背景

本内容是来自书籍《Head First 设计模式》的第一章,设计模式入门

二、工具箱的工具(本章) 1、OO基础
  1. 封装
  2. 继承
  3. 多态
  4. 抽象
2、OO原则
  1. 封装变化
  2. 面向接口编程,而非面向实现编程
  3. 组合优于继承
3、OO模式
  1. 策略模式,所谓策略模式就是定义算法族并将其分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。

算法族:白话讲就是一个对象的一组行为,但是我们通常将一组行为称之为“一族算法”。

三、例子展示

《Head First设计模式》使用鸭子举例,从一开始简单的封装实现鸭子游泳、叫的行为,到后来行为的添加之后导致现有设计的弹性不足(可复用、可扩展、可维护能力大大折扣),作者将OO基础&原则结合起来,设计一个应对鸭子行为添加时弹性较大的系统,这种模式称之为策略模式。

1、初期的鸭子系统 a.UML图


鸭子有游泳、叫以及展示自己品种的能力,Duck超类将swim() & quack()实现了,供子类直接调用,展示品种定义为抽象方法供子类去实现。早期看起来,采用继承的方式设计好像是没有问题的。

思考一下,当出现下面场景时现有的设计还是否合理?

  1. 如果产品要求有的鸭子是会飞的
  2. 如果产品要求并不是所有的鸭子都会叫,并且会叫的鸭子叫的方式也有可能不同
2、中期的鸭子系统 a.UML图


首先考虑利用接口定义行为,特殊的鸭子实现特定的接口,来达到具备某种能力的目的。这种方案,看似可行,其实对于代码的可复用性是打击性的。例如,此次需求需要实现几十种会飞的鸭子,那么我们就需要实现几十次的fly方法,这个系统几乎没有复用,成本是非常高的。

3、最终的鸭子系统 a.UML图

b.如何设计?

根据前面提到的设计原则:

  1. 封装变化:我们将飞行行为与呱呱叫行为都独立出来并进行了封装
  2. 面向接口编程而非实现:在Duck中,我们声明了两个变量(flyBehavior & quackBehavior),定义了两个set方法用于修改这两个变量,变量的实例是什么我不关心,我只关心我能够调用它的fly or quack这样的关键方法就行,这些方法具体是如何实现的我就不关心了
  3. 组合优于继承:在第二条中提到声明了两个变量,也就是两个变化的行为,Duck与这两个行为之间的关系是Has-a,而不是Is-a,有时候“有一个”比“是一个”更好
c.模式

而最终的这个系统运用的就是策略模式,它将算法族与使用算法的客户独立开来,可以相互替换(我可以在运行时让鸭子会叫,也可以让它不会叫)

三、代码 1. Duck相关 a.Duck
package com.markus.designpatterns.chapter1.duck;

import com.markus.designpatterns.chapter1.behavior.FlyBehavior;
import com.markus.designpatterns.chapter1.behavior.QuackBehavior;
import com.markus.designpatterns.chapter1.behavior.concrete.FlyNoWay;
import com.markus.designpatterns.chapter1.behavior.concrete.MuteQuack;

public abstract class Duck {
  private FlyBehavior flyBehavior;
  private QuackBehavior quackBehavior;

  public Duck() {
    // 默认鸭子不会飞 & 不会叫
    this.flyBehavior = new FlyNoWay();
    this.quackBehavior = new MuteQuack();
  }

  public void swim() {
    System.out.println("I can swim!");
  }

  abstract public void display();

  public void performFly(){
    flyBehavior.fly();
  }

  public void performQuack(){
    quackBehavior.quack();
  }

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

  public void setQuackBehavior(QuackBehavior quackBehavior) {
    this.quackBehavior = quackBehavior;
  }
}

b.Duck子类
public class DecoyDuck extends Duck{
  @Override
  public void display() {
    System.out.println("I am a Decoy Duck!");
  }
}
public class MallardDuck extends Duck{
  @Override
  public void display() {
    System.out.println("I am a mallard duck!");
  }
}
public class RedheadDuck extends Duck{
  @Override
  public void display() {
    System.out.println("I am a Redhead Duck!");
  }
}
public class RubberDuck extends Duck{
  @Override
  public void display() {
    System.out.println("I am a Rubber Duck!");
  }
}
2、行为相关 a.Fly
public interface FlyBehavior {
  void fly();
}
public class FlyNoWay implements FlyBehavior {
  @Override
  public void fly() {

  }
}
public class FlyWithWings implements FlyBehavior {
  @Override
  public void fly() {
    System.out.println("I have wings, so I can fly!");
  }
}
b.Quack
public interface QuackBehavior {
  void quack();
}
public class MuteQuack implements QuackBehavior {
  @Override
  public void quack() {

  }
}
public class Quack implements QuackBehavior {
  @Override
  public void quack() {
    System.out.println("quack");
  }
}
public class Squeak implements QuackBehavior {
  @Override
  public void quack() {
    System.out.println("squeak");
  }
}

3、测试Demo
public class DuckDisplayDemo {
  public static void main(String[] args) {
    Duck duck = new RedheadDuck();
    duck.display();
    duck.swim();
    //默认状态下不会飞、不会叫
    duck.performFly();
    duck.performQuack();
    System.out.println();
    //进行手动赋能
    duck.setFlyBehavior(new FlyWithWings());
    duck.performFly();
    duck.setQuackBehavior(new Quack());
    duck.performQuack();
  }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/300995.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号