【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.rhkb.cn/news/181903.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

spring-boot中实现分片上传文件

一、上传文件基本实现 1、前端效果图展示&#xff0c;这里使用element-ui plus来展示样式效果 2、基础代码如下 <template><div><el-uploadref"uploadRef"class"upload-demo":limit"1":on-change"handleExceed":auto-…

【算法】单调栈 每日温度 接雨水

文章目录 例题739. 每日温度42. 接雨水 相关练习1475. 商品折扣后的最终价格901. 股票价格跨度1019. 链表中的下一个更大节点84. 柱状图中最大的矩形 单调栈【基础算法精讲 26】 例题 739. 每日温度 https://leetcode.cn/problems/daily-temperatures/description/ 提示&a…

Git 的基本操作 ——命令行

Git 的工作流程 详解如下&#xff1a; 本地仓库&#xff1a;是在开发人员自己电脑上的Git仓库,存放我们的代码(.git 隐藏文件夹就是我们的本地仓库) 远程仓库&#xff1a;是在远程服务器上的Git仓库,存放代码(可以是github.com或者gitee.com 上的仓库,或者自己该公司的服务器…

php去除字符串两边空格空字符串换行方法

在PHP中&#xff0c;可以使用以下几种方法去除字符串两边的空格、空字符串和换行符&#xff1a; 使用trim()函数去除字符串两边的空格和空字符串&#xff0c;例如&#xff1a; $str " Hello World! "; $trimmed trim($str); echo $trimmed; 使用preg_replace(…

Angular-07:组件生命周期

三个阶段&#xff1a; ① 挂载阶段1.1 constructor1.2 ngOnInit ② 更新阶段2.1 ngOnChanges2.2 ngAfterViewInit2.3 ngAfterContentInit2.4 ngDoCheck ③ 卸载阶段3.1 onOnDestroy ④ 在组件中添加所有方法并打印 该表按照执行顺序编写 编号函数名实现名说明1constructorcons…

Java 开发常用的 Linux 命令

基本操作 Linux关机,重启 # 关机 shutdown -h now# 重启 shutdown -r now查看系统,CPU信息 # 查看系统内核信息 uname -a# 查看系统内核版本 cat /proc/version# 查看当前用户环境变量 envcat /proc/cpuinfo# 查看有几个逻辑cpu, 包括cpu型号 cat /proc/cpuinfo | grep name …

【Spring Boot 源码学习】JedisConnectionConfiguration 详解

Spring Boot 源码学习系列 JedisConnectionConfiguration 详解 引言往期内容主要内容1. RedisConnectionFactory1.1 单机连接1.2 集群连接1.3 哨兵连接 2. JedisConnectionConfiguration2.1 RedisConnectionConfiguration2.2 导入自动配置2.3 相关注解介绍2.4 redisConnectionF…

FreeRTOS笔记【一】 任务的创建(动态方法和静态方法)

一、任务创建和删除API函数 函数描述xTaskCreate()使用动态的方法创建一个任务xTaskCreateStatic()使用静态的方法创建一个任务xTaskCreateRestricted()创建一个使用MPU进行限制的任务&#xff0c;相关内存使用动态内存分配vTaskDelete()删除一个任务 二、动态创建任务 2.1 …

C语言——选择排序

完整代码&#xff1a; //选择排序 // 选择排序是一种简单直观的排序算法。它的工作原理如下:首先在未排序序列中找到最小&#xff08;大&#xff09;元素&#xff0c;存放到排序序列的起始位置&#xff0c;然后&#xff0c;再从剩余未排序元素中继续寻找最小&#xff08;大&am…

已完结,给小白的《50讲Python自动化办公》

大家好&#xff0c;这里是程序员晚枫&#xff0c;小红薯也叫这个名。 写在前面 上个周末去成都参加了第8届中国开源年会&#xff0c;认识了很多行业前辈和优秀的同龄人。 我发现在工作之外还能有一番事业的人&#xff0c;都有一个让我羡慕的共同点&#xff1a;有一个拿得出手…

Ubantu安装教程(其实和之前CentOS差不多)

文章目录 VM安装见下方参考链接Ubuntu安装我的是Ubuntu22.04.3官网下载我下载的桌面版LTS代表长期支持-这意味着五年的免费安全和维护更新选好版本点击下载就好&#xff08;注意桌面版和服务器版&#xff09; 搭建虚拟机个性化名字自定义安装位置不知道就先默认就好&#xff0c…

Java与Redis的集成

目录 Java连接Redis 导入依赖 Redis服务器准备 建立连接 Java操作Redis常用类型数据 Redis字符串(String) Redis哈希(Hash) Redis列表&#xff08;List&#xff09; Redis集合&#xff08;Set&#xff09; Redis有序集合&#xff08;Sorted Set&#xff09; Redis在项目应用…

类和对象解析

导言&#xff1a; Java是一门纯面向对象的语言&#xff0c;在面对对象的世界里&#xff0c;一切皆为对象。而对象的创建又和类的定义息息相关。本文主要阐述了类和对象的使用与理解。解释类的定义方式以及对象的实例化&#xff0c;类中的成员变量和成员方法的使用&#xff0c;…

Python基础入门例程45-NP45 禁止重复注册(条件语句)

最近的博文&#xff1a; Python基础入门例程44-NP44 判断列表是否为空&#xff08;条件语句&#xff09;-CSDN博客 Python基础入门例程43-NP43 判断布尔值&#xff08;条件语句&#xff09;-CSDN博客 Python基础入门例程42-NP42 公式计算器&#xff08;运算符&#xff09;-C…

吴恩达《机器学习》6-1->6-3:分类问题、假设陈述、决策界限

一、什么是分类问题&#xff1f; 在分类问题中&#xff0c;我们试图预测的变量&#x1d466;是离散的值&#xff0c;通常表示某种类别或标签。这些类别可以是二元的&#xff0c;也可以是多元的。分类问题的示例包括&#xff1a; 判断一封电子邮件是否是垃圾邮件&#xff08;二…

基于鹰栖息算法的无人机航迹规划-附代码

基于鹰栖息算法的无人机航迹规划 文章目录 基于鹰栖息算法的无人机航迹规划1.鹰栖息搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要&#xff1a;本文主要介绍利用鹰栖息算法来优化无人机航迹规划。 1.鹰栖息…

汽车标定技术(二)--基于XCP的标定测量实战

目录 1.工程创建 1.1 新建工程 1.2 设备配置 1.3 标定观测 1.4 刷写 2.原始hex文件与标定文件的合并 2.1 修改memory segment file 2.2 标定量地址偏移 ​编辑 2.3 标定后与原始hex文件合并 2.4 标定后直接merge 2.5 不用对ram地址进行偏移实现hex文件合并 本文使用…

linux 安装 elasticsearch 全教程

一、去 elasticsearch官网找到Linux版本的下载链接 地址https://www.elastic.co/cn/downloads/elasticsearch 二、在linux 中用wget下载 wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.10.4-linux-x86_64.tar.gz三、下载成功后解压文件 tar -x…

Quartz之JDBC-JobStoreTX配置

一、前言 上篇 《Quartz介绍》中使用的是RAMJobStored存储调度信息&#xff0c;当进程终止调度信息会丢失&#xff0c;本篇我们介绍使用JDBCJobStore来存储调度信息&#xff08;jobs、Triggers和日历&#xff09;。 二、Quartz 表结构 可以从官网&#xff08;http://www.qua…

java入门-JDK下载与安装

1、下载jdk Java 的产品叫JDK&#xff08;Java Development Kit: Java开发者工具包&#xff09;&#xff0c;必须安装JDK才能使用java 1、官网地址 https://www.oracle.com/java/ https://www.oracle.com/java/technologies/downloads/ 目前比较稳定的版本为 JDK17. 我们就安…