【Head First 设计模式】策略模式
文章目录
- 一、背景
- 二、工具箱的工具(本章)
- 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基础
- 封装
- 继承
- 多态
- 抽象
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();}
}
【Head First 设计模式】策略模式相关推荐
- Python设计模式-策略模式
Python设计模式-策略模式 代码基于3.5.2,代码如下; #coding:utf-8 #策略模式class sendInterface():def send(self,value):raise ...
- 关于设计模式——策略模式-Strategy Pattern
文章目录 1 策略模式 1.1 模拟鸭子 1.2 设计原则 1.3 整合行为 1.4 模拟鸭子代码的代码 1.5 动态设定行为 1.6 重新查看整体 1.7 继承和组合 1.8 总结 1.9 优劣期间 ...
- [设计模式] ------ 策略模式
策略模式 它定义了算法家族,分别封装起来,让他们直接可以互相替换,此模式让算法的变化,不会影响到使用算法的客户 其实很简单,可能很多人都用到了,只不过还不知道这就是策略模式而已. 比如定义一个接口A, ...
- java 策略模式 促销_java设计模式——策略模式
一. 定义与类型 定义:针对一组算法,将每一种算法都封装到具有共同接口的独立的类中,从而是它们可以相互替换.策略模式的最大特点是使得算法可以在不影响客户端的情况下发生变化,从而改变不同的功能.当代码中 ...
- Springboot 使用设计模式- 策略模式
前言 直白点,什么场景我们需要使用到设计模式- 策略模式. 在平常的springboot项目里面做CRUD,我们的习惯性基本是 一个mapper,一个service,一个serviceImpl. 但是 ...
- 李建忠设计模式——策略模式Strategy
目录 1.策略模式定义 1.动机 2.模式定义 3.结构 2.实现例子 1.问题描述 2.代码实现 3.要点总结 4.参考 1.策略模式定义 1.动机 软件构建过程中,某些对象使用的算法可能多种多样, ...
- 15. 星际争霸之php设计模式--策略模式
题记 ============================================================================== 本php设计模式专辑来源于博客(jy ...
- Java设计模式-策略模式作业
Java设计模式-策略模式作业,所有类和接口均在一个package内 文章目录 前言 一.作业内容 二.具体实现 1.类图 2.Strategy接口 3.PreCopyStrategy类 4.Post ...
- 设计模式-策略模式2.0
设计模式-策略模式2.0 前面文章我们说过了传统的策略模式的实现,本文我们简单说下设计模式中的升级版的策略模式,策略模式2.0. 代码实现 talk is cheap show me the code ...
- 设计模式-策略模式(Strategy)-Java
设计模式-策略模式(Strategy)-Java 目录 文章目录 1.前言 2.示例案例-电影票打折方案 3.策略模式概述 3.1.策略模式定义 3.2.策略模式结构 3.3.策略模式结构图中角色 3 ...
最新文章
- fiddler不能抓取浏览器数据_抓包软件 Fiddler 了解一下?
- 八、日志分析系统Nginx,Beats,Kibana和Logstash
- 麻省理工计算机科学录取条件,2018美国留学:麻省理工学院托福分数最低录取要求...
- .NET Core多平台项目模板eShopOnContainers编译手记
- Lucene-3.0.0配置
- Linux C 数据结构—-循环链表
- 发现了imageio文档中有代替scipy.misc的说明
- 数据结构基础(5) --归并排序
- 信息学奥赛一本通 1844:【06NOIP提高组】金明的预算方案 | 洛谷 P1064 [NOIP2006 提高组] 金明的预算方案
- 12.看板方法---度量和管理报告
- C#——WebApi 接口参数传参详解
- testlink xml转excel
- Python中的 SciPy 样条曲线插值
- 单点登录(SSO) --UCenter技术实现
- mindspore执行 core dump问题
- 『光纤交换机级联设置 』光纤跳线及光纤交换机端口级联类型
- Openssh rpm 包制作
- 数据分析基础——基本运算
- 【JAVA】关于自动化测试所需要学习的java基础知识笔记
- PAT 乙级 1033 旧键盘打字 python
热门文章
- fastboot刷boot命令
- 列梅兹remez算法求解最佳一致逼近多项式(C语言实现)
- Disney验厂初审及跟进审核的定义与区别
- python京东自动签到_爬虫实战【10】利用Selenium自动登陆京东签到领金币
- google map谷歌地图瓦片地址无偏移矢量地图电子地图影像地图
- 【ASM9260T】【LINUX-3.10】asm9260t芯片简介
- Web程序设计基础期末大作业——模仿QQ飞车手游S联赛官网编写的网页
- java专业技能写什么_Java开发工程师专业技能范例列表
- linux otg 大容量存储设备,大容量存储个人设备有哪些 | 教你一招解决大容量存储多种问题_什么值得买...
- 信捷 XDH EtherCAT 单轴指令