Head First Design Mode(2)-设计模式入门(策略模式)

2023-10-27

该系列文章系个人读书笔记及总结性内容,任何组织和个人不得转载进行商业活动!

 

设计模式入门:

    欢迎来到设计模式世界;

    我们会看到设计模式的用途和优点,再看看关键的OO原则,通过实例来了解模式是如何运作的;

    以往是代码复用,现在是经验复用;

 

模拟鸭子的应用:

    Duck(鸭子)会Quark(呱呱叫)和 Swim(游泳);

    我们定义超类Duck::quark();swim();dispaly();

        外观display方法是一个抽象方法,因为每种鸭子的外观各有不同;

    ADuck,BDuck子类型的鸭子实现了display()方法;共同继承自Duck类;

 

这是一种继承的方式,在学习Java时一定学习过类似的题目;

 

现在让鸭子能飞:

    利用继承,我们在Duck类中添加fly()方法;

    但是,很多“橡皮鸭子”飞来飞去,因为父类中的方法会被所有子类继承;

    导致很多不适合’飞’行为的子类也具有了该行为;

 

当涉及“维护”时,为了“复用”(reuse)目的而使用继承,结局并不完美;

 

继承下的做法:

    在橡皮鸭类中把fly()方法覆盖掉,让它什么都不做;

    带来的问题是,其他类型的鸭子都会受到影响,你不得不为其他不会叫的鸭子类重写fly()方法;

    而当加入新鸭子时,由不得不检查这些方法;

 

我们不想代码在多个子类中重复,又很难知道鸭子的全部行为,最重要的,这样修改 会导致 牵一发而动全身,这显然不是我们想要的;

 

利用接口:

    需要一个清晰的方法,让某些鸭子类型可飞或可叫;

    我们把fly()和quark()分别声明在接口Flyable和Quarkable中,需要飞的鸭子实现相应的接口即可;

 

但这个设计真的好吗,这是一个多对多的关系,如果有20种鸭子,他们的飞行行为需要调整,那简直就是灾难;

 

我们看到:

    继承并不是适当的解决方式;

    接口解决了一部分问题,但是代码却没法有效的复用;

 

采用良好的OO软件设计原则:

    软件开发的不变真理就是变化——不管当初软件设计的多好,一段时间后,总要成长与改变;

 

把问题归零:

    我们知道了使用继承并不能很好的解决问题,因为鸭子的行为在子类里不断的变化,让所有的子类都有这些行为是不恰当的;

    使用接口虽然解决了一部分问题,但是接口只有声明不具有实现的代码,所以实现接口无法达到代码复用;

 

适应此情况的设计原则:

    找到应用中变化之处,独立出来,不要和不需要变化的代码混在一起;

    变化的代码进行封装,使代码变化引起的后果变小,系统变得更有弹性;

 

该原则的另一种思考方式:

    把会变化的部分取出来并封装起来,以便以后轻易地改动或扩充此部分,而不影响不需要变化的其他部分;

 

这几乎是所有设计模式背后的精神所在“系统中的某部分改变不会影响其他部分”;

 

分开变化的 和 不变的:

    新建两组类与Duck无关的,一组是fly相关,一组是quark相关,每组类将实现各自的动作(高飞类、底飞类,咕咕叫类、嘎嘎叫类…);

    这样取出来的一组fly相关类,就可以用来表示Duck的fly行为,一个鸭子可以有多种行为;

 

设计鸭子的行为:

    一切能有弹性;比如,新建一个绿头鸭,初始的飞行行为是高飞,在运行过程中,我们可以动态的改变成底飞;

 

第二个设计原则:

    针对接口编程,而不是针对实现编程;

 

比如fly行为被放在多个分开的类中,而这些类专门提供fly行为接口的实现;

这样鸭子类就不再需要知道行为的实现细节;

 

我们用接口代表了行为:FlyBehavior、QuarkBehavior;

    由具体的行为类而不是Duck类来实现行为接口;

 

以往是行为来自超类的具体实现,或继承某个接口由子类自行实现而来;这两种做法都依赖于实现,没办法改变行为;

 

“针对接口编程”真正的意思是“针对超类型编程”:

    因为所有实现接口的类,其接口类型,都可以看作是实现类的超类(或父类);

    由于实现了相同的接口,他们就是相同的类型了,变量声明类型都是超类型;

    这利用了多态,执行时会根据实际状况执行真正的行为;

    超类型,通常是一个抽象类或一个接口;

 

如此,只要是具体实现此超类型的类所产生的对象,都可以指定给这个变量;这意味着,声明类时不用理会以后执行时的真正对象类型;

 

针对实现编程:

    Dog dog1 = new Dog();
    dog1.bark();

 

针对接口编程:

    Animal animal = new Dog();
    animal.makeSound();

 

而且,子类实例化执行的new动作不再需要在代码中硬编码,实际的子类型是什么不一定要知道,我们只关心他是否能正确的执行相应的动作;

 

实现鸭子的行为:

    FlyBehavior-interface: fly();

        FlyHigh: :fly();

        FlyLow: :fly();

    QuarkBehavior: quark();

        QuarkGugu: :quark();

        QuarkGuagua: :quark();

 

    这样的设计这些行为被其他代码复用,因为它们已经和鸭子无关了;

 

整合鸭子的行为:

    鸭子现在将飞和叫的动作“委托”给了其他对象处理,而不是用Duck类的叫和飞;

1)在Duck类中加入两个实例变量,均声明为接口类型;

2)使用performFly()和performQuark()方法,其中通过实例变量调用fly()和quark();

    鸭子对象不亲自处理叫和飞的行为,而是委托给两个实例变量对象;

3)新建鸭子DuckSub1,在初始化方法中为实例变量赋值:高飞 咕咕叫!(实例变量是从父类继承来的)

 

编译运行下:

bogon:第一章 huaqiang$ javac *.java
bogon:第一章 huaqiang$ java DuckDrive
Fly high !
Quark gugu !
DuckSub1!

由于实例变量是接口类型的,我们也可以为它指定相同接口不同的实现类;

 

动态设定行为:

    加入如下两个方法;

public void setFlyBehavior(FlyBehavior fb){
    flyBehavior = fb;    
}

public void setQuarkBehavior(QuarkBehavior qb){
    quarkBehavior = qb;    
}

这样,就可以把 新的行为实现设定给指定的鸭子;

 

封装行为的大局观:

    稍稍改变描述的方式,我们把一组行为,描述为一族算法;

    那么,算法就表示鸭子能做的事,类似的场景:用一群算法计算某城市的销售税金;

 

封装飞行行为(各种飞行方式):一族算法;

……

 

我们发现同一族里的算法是可以互换的;

 

在上述示例中一定要明确几种关系:IS-A、HAS-A、IMPLEMENTS;

 

有一个的关系可能比是一个更好:

    每个鸭子有一个FlyBehavior和QuarkBehavior,好将飞和叫 委托给他们代为处理;

    这里将两个行为类 进行了 “组合”;鸭子的行为不是继承来的,而是适当行为对象组合来的;

 

第三个设计原则:

    多用组合,少用继承;

 

实用组合将算法族封装成类,在符合正确的接口标准时,建立的系统也很有弹性;

 

此间,我们用了学到的第一个设计模式:策略模式;

 

策略模式:

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

 

如何使用设计模式:

    我们开发需要使用别人设计好的库和框架;我们挑选好组件,把他们放到合适的地方;

    但是,库和框架无法帮助我们将应用组织成容易了解、容易维护、具有弹性的架构,所以需要设计模式,并在合适的场景中使用之;

    

设计模式告诉我们如何组织类和对象已解决某种问题;

 

有很多面向对象的原则,使用所有模式,当没有找到合适的设计模式时,遵循这些原则即可,下一章我们继续学习;

 

总结:

1.知道OO基础,不足以设计出良好的OO系统;

2.良好的OO设计必须具备 复用 可扩充 可维护三个特性;

3.模式可以让我们建造出具有良好OO设计质量的系统;

4.模式被认为是经历验证的OO设计经验;

5.模式不是代码,而是针对设计问题的通用解决方案;

6.大多数模式和原则,都着眼于软件变化的主题;

7.我们常把系统中会变化的部分抽出来封装;

8.模式让开发人员之间有共享的语言,能够最大化沟通的价值;

 

OO基础:

    抽象 封装  多态 继承;

OO原则:

    封装变化

    多用组合,少用继承

    针对接口编程,不针对实现编程;

OO模式:

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

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Head First Design Mode(2)-设计模式入门(策略模式) 的相关文章

  • 在 React 中应用设计模式:策略模式

    这篇文章是关于我们许多人在 React 和前端开发中遇到的一个问题 有时甚至没有意识到这是一个问题 在不同的组件 钩子 实用程序等中实现了一段逻辑 让我们深入了解问题的详细信息以及如何解决它 正如标题所暗示的 我们将使用策略模式来解决它 问
  • JAVA设计模式(21) —装饰(Decorator)模式

    定义 动态的给一个对象添加一些额外的职责 就增加功能来说 Decorator模式相比生成子类更为灵活 类型 对象结构型模式 别名 包装模式 Wrapper 类图 Decorator装饰模式是一种结构型模式 它主要是解决 过度地使用了继承来扩
  • 设计模式-策略模式

    策略模式是一种行为型设计模式 其主要目的是允许在运行时选择算法的行为 在Java中 我们可以使用策略模式来根据不同的条件动态地选择不同的算法 下面是一个示例代码 展示了如何在Controller中确定是什么策略 以及如何调用相应的Servi
  • 设计模式---适配器模式

    适配器模式 基本介绍 适配器模式 Adapter Pattern 将某个类的接口转换成客户端期望的另一个接口表示 主的目的是兼容性 让原本因接口不匹配不能一起工作的两个类可以协同工作 其别名为包装器 Wrapper 适配器模式属于结构型模式
  • 1.单例模式之饿汉式

    单例模式总结 特点 构造方法私有 提供一个全局访问点 实现方式 有很多 分四篇分别总结1 饿汉式 2 懒汉式 3 注册式 4 ThreadLocal 优点 内存中只有一个实例 减少内存开销 避免对资源多重占用 设置全局访问点 严格控制访问
  • Java 动态代理和静态代理 详解(结合代码实列)

    文章目录 Java 动态代理和静态代理的区别 下面是一个结合代码示例 运行上述代码 输出如下 总结 Java 动态代理和静态代理的区别 动态代理和静态代理是两种不同的代理模式 它们在代理对象的创建和使用方式上有所不同 静态代理 静态代理是在
  • 开放-封闭原则

    一 定义 开放 封闭原则 是说软件实体 类 模块 函数等等 应该是可扩展的 但是不可修改 ASD 这个原则其实是有两个特征 一个是说 对于扩展是开放的 Open for extension 对于更改是封闭的 Closed for modif
  • 观察者模式(推模型+拉模型)

    观察者模式 Observer Pattern 当一个对象被修改时 会自动通知它的依赖对象 现在我们是新闻社 要向所有新闻订阅者推送新闻 那么该如何实现呢 经过思考我们不难发现一家新闻社一般对应的是多个新闻订阅者 那么我们先从新闻社开始入手
  • @Async 异步调用

    策略模式 一 Async 基础 基础使用示例 二 Async 与线程池 实现AsyncConfigurer 替换默认线程池 指定 Async 使用的线程池 一 Async 基础 在编写接口时大多数情况下都是通过同步的方式来实现交互处理 在特
  • Springboot中使用策略模式+工厂模式

    策略模式和工厂模式相信大家都比较熟悉 但是大家有没有在springboot中实现策略和工厂模式 具体策略模式和工厂模式的UML我就不给出来了 使用这个这两个模式主要是防止程序中出现大量的IF ELSE IF ELSE 接下来咱们直接实现 项
  • 策略+工厂+反射记录一次switch代码简化过程

    遇到的问题 一张记录表 记录了10个业务的字段 一个入参type说明了要修改哪个字段 最初是通过switch type case 来做的 但是涉及这样子的判断多了 每次都要不断的switch 并且case里面不同方法有不同的处理 一个公共的
  • 智能优化算法-战争策略算法War Strategy Optimization Algorithm(附Matlab代码)

    引言 战争策略算法War Strategy Optimization Algorithm是基于军队在战争中的战略运动 将战争策略建模为一个优化过程 每个士兵都动态地向最优值移动 该算法对两种流行的战争策略 进攻和防御策略进行建模 士兵在战场
  • 注入多个实现类【JAVA】(设计模式之策略模式)项目实际场景【Spring boot】

    文章目录 业务场景 策略模式的概念 代码示例 1 创建一个接口类 2 创建接口类的实现类 3 创建脚手架 box类 4 最后创建一个实现工厂类 MsgBeanFactory 5 测试代码 6 输出结果 总结 业务场景 最近有一个场景消息发送
  • java设计模式——享元模式(Flyweight Pattern)

    概述 面向对象技术可以很好地解决一些灵活性或可扩展性问题 但在很多情况下需要在系统中增加类和对象的个数 当对象数量太多时 将导致运行代价过高 带来性能下降等问题 享元模式正是为解决这一类问题而诞生的 享元模式通过共享技术实现相同或相似对象的
  • Gof23设计模式之命令模式

    1 概述 将一个请求封装为一个对象 使发出请求的责任和执行请求的责任分割开 这样两者之间通过命令对象进行沟通 这样方便将命令对象进行存储 传递 调用 增加与管理 2 结构 命令模式包含以下主要角色 抽象命令类 Command 角色 定义命令
  • Gof23设计模式之原型模式

    1 概述 用一个已经创建的实例作为原型 通过复制该原型对象来创建一个和原型对象相同的新对象 2 结构 原型模式包含一下角色 抽象原型类 规定了具体原型对象必须实现的clone 方法 具体原型类 实现了抽象圆形类的clone 方法 它是可被复
  • 考虑virtual函数以外的其他选择——条款35

    假设你正在写一个视频游戏软件 你打算为游戏内的人物设计一个继承体系 你的游戏术语暴力砍杀类型 剧中人物被伤害或因其他因素而降低健康状态的情况并不罕见 你因此决定提供一个成员函数healthValue 它会返回一个整数 表示人物的健康程度 由
  • JAVA设计模式(二)工厂模式与观察者模式

    工厂模式 工厂模式顾名思义则是类似于一个工厂制造产品的模式 如富士康需要制造自己的产品 而同类产品有多种 如手机有各个品牌和型号一样 明白了工厂模式的含义 我们来想想这个模式具体是怎么回事 首先需要的是一个工厂于是就需要一个Factory类
  • Java设计模式-单例模式

    单例模式 在有些系统中 为了节省内存资源 保证数据内容的一致性 对某些类要求只能创建一个实例 这就是所谓的单例模式 单例模式的定义与特点 单例 Singleton 模式的定义 指一个类只有一个实例 且该类能自行创建这个实例的一种模式 例如
  • 策略模式在数据接收和发送场景的应用

    其他系列文章导航 Java基础合集 数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 文章目录 其他系列文章导航 文章目录 前言 一 策略模式改进 1 1 策略模式的定义 1 2 策略模式的结构通常包括以下组成部分 1 3

随机推荐

  • WEB前端之html img标签引用本地图片

    我觉得语法大家都应该明白怎么写 img src img demo PNG 很简单 但是我在第一次写的时候总是出现图片加载不出来的情况 然后发现 只要把图片文件夹放在工程文件夹中就可以正常调用了 这样就解决了这个问题
  • 【格局】一张图看懂全球人工智能竞争格局

    5月24日 由科技部新一代人工智能发展研究中心 中国科学技术发展战略研究院联合国内外十余家机构编写 中国科学技术信息研究所 教育部学校规划建设中心 中国科学院自动化所 中国社科院工业经济研究所 上海市科学学研究所等科研机构 以及清华大学 中
  • Vue3+TypeScript+Router+Vuex+Ant-Design-Vue项目(二)—— Ant-Design-Vue基础组件使用

    新建一个组件 TestPage vue
  • Allegro 使用技巧

    这几个分别是通用 布局 布线 右键不一样 注意区别 最后一个是修剪直角 Allegro技巧有太多了 就先选择我们会用到的10个类型 Allegro封装神器FPM 写进教科书的网友作品 快速生成封装 快速丝印 丝印摆放总共分三步 第一步 调整
  • TensorFlow2模型的保存与恢复

    keras API 保存与加载 保存 Sequential 模型和 Functional 模型 建立用于实验的模型 Sequential 模型和 Functional 模型保存方法相同 用Functional 模型演示 from tenso
  • GAUSSIAN MIXTURE VAE: LESSONS IN VARIATIONAL INFERENCE, GENERATIVE MODELS, AND DEEP NETS

    Not too long ago I came across this paper on unsupervised clustering with Gaussian Mixture VAEs I was quite surprised es
  • 在idea中pom.xml添加sparkSQL依赖

    在idea中 如果没有sparkSQL的依赖 需要现在pom xml 中添加依赖
  • MindStudio算子开发案例(TensorFlow框架AI CPU算子开发全流程)

    1 介绍 B站视频链接 TensorFlow框架AICPU算子开发全流程 哔哩哔哩 bilibilihttps www bilibili com video bv1dY411c7sd 本文旨在帮助用户使用CANN架构和MindStudio平
  • 粒子群算法(PSO)优化的BP神经网络预测,PSO-BP回归预测

    关注 智能算法及其模型预测 clc clear all close all restoredefaultpath tic 导入数据 训练集 190个样本 P xlsread data training set B2 G191 T xlsre
  • nginx根据二级域名做请求转发

    在server 段中添加以下location location root html index index html index htm 处理二级域名fund cmbchina com转发 if http host cmbchina com
  • 华为数通HCIP-ISIS原理与配置

    IS IS的基本概念 isis 中间系统到中间路由协议 链路状态路由协议 IGP 无类路由协议 IS IS是一种链路状态路由协议 IS IS与OSPF在许多方面非常相似 运行IS IS协议的直连设备之间通过发送Hello报文发现彼此 然后建
  • 深入 AXI4 总线(一)握手机制

    VALID READY 握手机制 AXI 总线共有 5 个独立的通道 分别为写地址 写数据 写回应 读地址 读数据通道 5 条通道相互独立 有一些细小的差别 但共同使用一套握手机制 VALID READY 机制 VALID READY 机制
  • 笔记: C语言中的骚操作 (带参宏定义及三目运算实例)

    带参宏定义及三目运算实例 带参宏定义 就是带参数的宏定义 类似函数 三目运算 A B C 即 A为真 则输出B 为假则输出C n 1输出高电平 define CON1 1 PC12 n n HAL GPIO WritePin GPIOC G
  • 2022年度游戏本行业数据报告:十大热门品牌销量排行榜

    2022年游戏本市场的总体局面是 产品竞争极为激烈 同时又各具特色卖点 今年的游戏本市场 市场格局并未有较大的变化 但是新技术 新产品层出不穷 各个游戏本厂商们通过不断创新 提升产品性能 推出了体验感更好的产品 满足了用户不同场景的应用需求
  • HTTP协议和编程实现

    1 HTTP协议 http协议是建立在TCP IP协议之上应用层协议 默认端口为80或者8080 http协议的的特点是无状态 无连接 在访问数据的时候才进行连接 不是长连接 http协议的报文传输的是ASCII码 在TCP IP协议之上
  • 面向对象程序设计的几个基本概念

    面向对象程序设计由6个概念组成 1 类 它是每一个Java程序的基本结构 它包含数据域和数据操作机制 类提供了创建这些软件对象的模板 2 对象 对象是以类为模板创建的实例 以各类可以用来生成任意多个对象 3 封装性 允许或禁止访问类或对象的
  • Centos7 Shell脚本监控磁盘容量实现钉钉告警

    前言 此脚本用来监控服务器磁盘容量实现钉钉告警功能 一 编写Shell脚本 创建脚本存放目录 存放在 data shell 下 mkdir p data shell vim data shell DingTalk Alert bin bas
  • 七款好用的项目管理软件

    TeamLab 它是一个在线商业协作和项目管理的平台 主要功能包括 项目管理 里程碑管理 任务 报表 事件 博客 论坛 书签 Wiki 即时消息等 TeamLab是专为中小型企业 团队打造的系统 使用SaaS解决方案的网站 也就是说 您可以
  • linux 部署Django + apache2 + python3

    之前在本地部署了Django的restful应用Django 从零开始实现简单的restful应用 现在把它部署到服务器上 安装 在部署过程中 很多需要的东西之前已经安装好 所以 python 3 我的服务器是ubuntu 16 04 预装
  • Head First Design Mode(2)-设计模式入门(策略模式)

    该系列文章系个人读书笔记及总结性内容 任何组织和个人不得转载进行商业活动 设计模式入门 欢迎来到设计模式世界 我们会看到设计模式的用途和优点 再看看关键的OO原则 通过实例来了解模式是如何运作的 以往是代码复用 现在是经验复用 模拟鸭子的应