当前位置: 首页 > news >正文

【Head First 设计模式】-- 策略模式

一、背景
Head First 设计模式第一章设计模式入门–策略模式

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

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

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

1、初期的鸭子系统
a.UML图
在这里插入图片描述

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

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

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

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

3、最终的鸭子系统
a.UML图
在这里插入图片描述

b.如何设计?
根据前面提到的设计原则:

封装变化:我们将飞行行为与呱呱叫行为都独立出来并进行了封装
面向接口编程而非实现:在Duck中,我们声明了两个变量(flyBehavior & quackBehavior),定义了两个set方法用于修改这两个变量,变量的实例是什么我不关心,我只关心我能够调用它的fly or quack这样的关键方法就行,这些方法具体是如何实现的我就不关心了
组合优于继承:在第二条中提到声明了两个变量,也就是两个变化的行为,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{@Overridepublic void display() {System.out.println("I am a Decoy Duck!");}
}
public class MallardDuck extends Duck{@Overridepublic void display() {System.out.println("I am a mallard duck!");}
}
public class RedheadDuck extends Duck{@Overridepublic void display() {System.out.println("I am a Redhead Duck!");}
}
public class RubberDuck extends Duck{@Overridepublic void display() {System.out.println("I am a Rubber Duck!");}
}

2、行为相关
a.Fly

public interface FlyBehavior {void fly();
}
public class FlyNoWay implements FlyBehavior {@Overridepublic void fly() {}
}
public class FlyWithWings implements FlyBehavior {@Overridepublic void fly() {System.out.println("I have wings, so I can fly!");}
}

b.Quack

public interface QuackBehavior {void quack();
}
public class MuteQuack implements QuackBehavior {@Overridepublic void quack() {}
}
public class Quack implements QuackBehavior {@Overridepublic void quack() {System.out.println("quack");}
}
public class Squeak implements QuackBehavior {@Overridepublic 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();}
}
http://www.lryc.cn/news/222594.html

相关文章:

  • 能链智电,“重”症在身
  • python 视频硬字幕去除 内嵌字幕去除工具 vsr
  • 蓝桥等考C++组别六级004
  • SpringBoot之Swagger
  • 抖音小店新的流量变现新时代!
  • 软件架构师
  • postman接口测试
  • 技术分享 | web自动化测试-PageObject 设计模式
  • Mall4cloud 微服务商城系统 2.0 发布
  • SpringBoot进制转换规则问题
  • 12.输入一个小于1000的整数,输出平方根(不是整数,输出整数部分)
  • Django框架的推导
  • 广东开放大学:电大搜题助力学子迎考利器
  • linux 7za 编译安装
  • 【Edge】微软Edge每次启动自动导入Chrome收藏夹,无法取消“每次启动浏览器时导入浏览数据”功能的解决方法(202311)
  • 报错RuntimeError: no valid convolution algorithms available in CuDNN
  • JSP通用材料收集归档系统eclipse定制开发mysql数据库BS模式java编程jdbc
  • 网络安全-零基础小白自学要点
  • SpringCloud——服务注册——Eureka
  • 大模型时代的编码习惯
  • 程序员怎样才能学好算法?这本书送几本给大家!
  • 2023-11-08 monetdb-事务-只有RR隔离级别-原因分析
  • 微信小程序:怎么在一个js中修改另一个js的数据(这里通过缓存进行实现)
  • 01-基于IDEA,Spring官网,阿里云官网,手动四种方式创建SpringBoot工程
  • map相关题目
  • JAVA 版小程序商城免费搭建 多商家入驻 直播带货 商城系统 B2B2C 商城源码之 B2B2C产品概述
  • moc_ XX.cpp 中的函数没有定义
  • 11.8代码
  • 常用的表单校验规则——邮箱/QQ/身份证号码/微信/电话/数字字母/整数/文本/密码等
  • Mysql数据库 11.SQL语言 储存过程 下 储存过程管理和游标