设计模式:HelloWorld之策略模式
一.概述
策略模式 定义了算法族,分别封装起来,让他们可以互相替换,此模式让算法的变化独立于使用算法的客户。
策略模式的三要素:
抽象策略角色: 策略类,通常由一个接口或者抽象类实现。
具体策略角色:包装了相关的算法和行为。
环境角色:持有一个策略类的引用,最终给客户端调用。
二.案例驱动
提出问题:要求做出一套模拟鸭子的游戏,游戏中会出现各种鸭子,它们一边游泳,一边呱呱叫。
分析:根据OO设计思想,无非就是使各种鸭子实现自己相应的功能即可,如鸭子游泳,鸭子呱呱叫。
解决方案1.0:设计一个接口(Duck),然后根据需要完成不同的实现,如红头鸭,绿头鸭。。。。
public interface Duck {
public abstract void quack();
public abstract void swim();
public abstract void display();
}
public MallardDuck implements Duck{
public abstract void quack(){
System.out.println("呱呱~~");
}
public abstract void swim(){
System.out.println("欢快的游泳~~");
}
public abstract void display(){
System.out.println("绿头鸭~~");
}
}
public RedHeadDuck implements Duck{
public abstract void quack(){
System.out.println("呱呱~~");
}
public abstract void swim(){
System.out.println("欢快的游泳~~");
}
public abstract void display(){
System.out.println("红头鸭~~");
}
}
突然增加一个新的需求,要求有野鸭,除了具有这两个功能外,还会飞(fly),同时还有一种橡皮鸭,叫声时吱吱。。
此时该方案便暴露了一下缺点。。。。
缺点:牵一发而动全身,我们很难知道所有鸭子的行为,当针对有些实现需要添加新的功能时
解决方案1.1
为了更加灵活,面向接口编程。
public interface Flyable {
public abstract void fly();
}
public interface Swimable {
public abstract void swim();
}
public interface Quackable {
public abstract void quack();
}
public RedHeadDuck implements Quackable implements Swimable {...}
public WildDuck implements Quackable implements Swimable implements Flyable {...}
如果有一万种鸭子,这种方式简直不敢想象,重复代码太多!
解决方案2.0
采用策咯模式解决此问题。
step1:把会变化的部分取出来,并封装起来,好让其他代码不受影响。
step2:封装行为的大局观
step3:代码实现
抽象策略角色
// 飞行行为
public interface FlyBehavior {
public abstract void fly();
}
// 叫声行为
public interface QuackBehavior {
public abstract void quack();
}
具体策略对象
// 橡皮鸭叫
public RubberDuckBehavior implements QuackBehavior {
public abstract void quack(){
System.out.println("吱吱~~");
}
}
// 野鸭叫
public WildDuckBehavior implements QuackBehavior {
public abstract void quack(){
System.out.println("嘎嘎~~");
}
}
// 大黄鸭叫
public YellowDuckBehavior implements QuackBehavior {
public abstract void quack(){
System.out.println("呱呱~~");
}
}
// 不会飞
public FlyNoWay implements FlyBehavior {
public abstract void fly(){
System.out.println("不会飞~~");
}
}
// 用翅膀飞
public FlyWithWings implements FlyBehavior {
public abstract void fly(){
System.out.println("用翅膀飞~~");
}
}
// 螺旋桨飞
public FlyLikePlane implements FlyBehavior {
public abstract void fly(){
System.out.println("用螺旋桨~~");
}
}
环境角色
抽象类
public abstract class Duck {
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
// 动态设定行为
public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}
public void setQuackBehavior(QuackBehavior quackBehavior) {
this.quackBehavior = quackBehavior;
}
public void performFly() {
flyBehavior.fly();
}
public void performQuack() {
quackBehavior.quack();
}
public abstract display() {}
public void swim() {
System.out.println("鸭子天生会游泳!");
}
}
实现
public class WildDuck implements Duck {
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public WildDuck() {
// 默认会飞,野鸭叫嘎嘎
this.flyBehavior = new FlyWithWings();
this.quackBehavior = new WildDuckBehavior();
}
// 动态设定行为
public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}
public void setQuackBehavior(QuackBehavior quackBehavior) {
this.quackBehavior = quackBehavior;
}
public void performFly() {
flyBehavior.fly();
}
public void performQuack() {
quackBehavior.quack();
}
public abstract display() {
System.out.println("这是一只野鸭!");
}
public void swim() {
System.out.println("鸭子天生会游泳!");
}
}
需求改变:野鸭的翅膀受伤,不会飞了
public static void main(String[] args) {
Duck duck = new WildDuck();
duck.setFlyBehavior(new FlyNoWay());
duck.performFly();// 输出:不会飞~~
}
需改改变:新增一只火箭鸭,能飞到太空,不会游泳,外形像火箭一样,叫嘎嘎
public RocketDuckFlyBehavior implements FlyBehavior {
public abstract void fly(){
System.out.println("飞到太空~~");
}
}
public class RocketDuck implements Duck {
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public WildDuck() {
// 默认会飞,野鸭叫嘎嘎
this.flyBehavior = new RocketDuckFlyBehavior();
this.quackBehavior = new WildDuckQuackBehavior();
}
// 动态设定行为
public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}
public void setQuackBehavior(QuackBehavior quackBehavior) {
this.quackBehavior = quackBehavior;
}
public void performFly() {
flyBehavior.fly();
}
public void performQuack() {
quackBehavior.quack();
}
public abstract display() {
System.out.println("外形像火箭~~");
}
public void swim() {
System.out.println("不会游泳");
}
}
三.策略模式的优缺点
优点:
1.策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族。恰当使用继承可以把代码转移到符类,从而避免重复代码 。
2.在策略模式中利用组合和委托来让环境角色拥有执行算法的能力,这也是继承的一种更轻便的替代方案。
3.提供了对开放—封闭原则的完美支持,将算法封装在独立的strategy中,使得它们易于切换,易于理解,易于扩展
4.利用组合、委托和多态等技术和思想,可以有效地避免多重条件选择语句
缺点:
1.客户端必须知道所有的策略类,区分他们之间的区别,并自行决定使用哪一个策略类。
2.针对每一种行为情况需要创建一个策略类,造成很多的策略类。
设计模式:HelloWorld之策略模式的更多相关文章
- 【转】设计模式 ( 十八 ) 策略模式Strategy(对象行为型)
设计模式 ( 十八 ) 策略模式Strategy(对象行为型) 1.概述 在软件开发中也常常遇到类似的情况,实现某一个功能有多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成 ...
- 设计模式 ( 十八 ) 策略模式Strategy(对象行为型)
设计模式 ( 十八 ) 策略模式Strategy(对象行为型) 1.概述 在软件开发中也经常遇到类似的情况,实现某一个功能有多种算法或者策略,我们能够依据环境或者条件的不同选择不同的算法或者策略来完毕 ...
- 《Head First 设计模式》[01] 策略模式
<Head First 设计模式>(点击查看详情) 1.写在前面的话 之前在列书单的时候,看网友对于设计模式的推荐里说,设计模式的书类别都大同小异,于是自己就选择了Head First系列 ...
- javascript设计模式--策略模式
javascript策略模式总结 1.什么是策略模式? 策略模式的定义是:定义一系列的算法,把他们独立封装起来,并且可以相互替换. 例如我们需要写一段代码来计算员工的奖金.当绩效为a时,奖金为工资的5 ...
- [head first 设计模式] 第一章 策略模式
[head first 设计模式] 第一章 策略模式 让我们先从一个简单的鸭子模拟器开始讲起. 假设有个简单的鸭子模拟器,游戏中会出现各种鸭子,此系统的原始设计如下,设计了一个鸭子超类,并让各种鸭子继 ...
- Python设计模式: 最佳的"策略"模式实践代码
Python设计模式: 最佳的"策略"模式实践代码 今天抽空看了下流畅的python,发现里面介绍了不少python自带的库的使用实例,用起来非常的优雅. 平时用Python来写爬 ...
- [设计模式] javascript 之 策略模式
策略模式说明 定义: 封装一系列的算法,使得他们之间可以相互替换,本模式使用算法独立于使用它的客户的变化. 说明:策略模式,是一种组织算法的模式,核心不在于算法,而在于组织一系列的算法,并且如何去使用 ...
- 设计模式:Strategy 策略模式 -- 行为型
设计模式 策略模式Strategy(对象行为型) 这是几年前写的文字(转载做的笔记更准确些),发觉还是废话多了点. 其实,核心就是5.结构中的UML图 5.1 和 5.2(新增).现在看这张图就觉得一 ...
- 设计模式浅谈----策略模式(c#及java实现)
一.何为策略模式 策略模式是行为型模式的一种,主要用于需要使用不同的算法来处理不同的数据对象时使用,是一种可以在运行时选择算法的设计模式.也称为政策模式. 主要解决:在有多种算法相似的情况下,使用 i ...
随机推荐
- python实现排序算法 时间复杂度、稳定性分析 冒泡排序、选择排序、插入排序、希尔排序
说到排序算法,就不得不提时间复杂度和稳定性! 其实一直对稳定性不是很理解,今天研究python实现排序算法的时候突然有了新的体会,一定要记录下来 稳定性: 稳定性指的是 当排序碰到两个相等数的时候,他 ...
- Python之进程
进程 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.在早期面向进程设计的计算机结构中,进程是程序的基本执行实体:在当代 ...
- SQL 语句 (二) --- SELECT
1 完整句法: SELECT [ ALL | DISTINCT TOP n [] WITH TIES select_list [INTO [new_table_name] ] [FROM {table ...
- ABP框架 - 我的第一个Web API
本文示例源代码地址https://github.com/lcyhjx/abp-training 上一篇我们已经对ABP是什么,能做什么.有了一个印象.那么接下来我们将动手使用ABP框架快速开发一个AP ...
- 【Python3.6+Django2.0+Xadmin2.0系列教程一】环境搭建及项目创建
由于工作需要,接触了大半年时间的Django+xadmin框架,一直没空对这块对进行相关的梳理.最近在同事的怂恿下,就在这分享下笔者的学习及工作经验吧. 好了,话不多说,下面开始进入正题: 环境需求: ...
- HTML5中meta属性大集合
1.声明文档的字符编码 <meta charset='utf-8'> 2.声明文档的兼容模式 <meta http-equiv="X-UA-Compatible" ...
- swiper 应用
swiper之PC端的广告页面[当前示例对应网站:http://shang.shuaishou.com/] plugins:[红线部分] html: <div class="banne ...
- react源代码重点难点分析
网上已经有不少react源码分析文档,但都是分析主流程和主要功能函数,没有一个是从reactDOM.render()入口开始分析源码把流程走通尤其是把复杂重要的细节环节走通直到把组件template编 ...
- spring data学习
在Spring Data模块中定义依赖: <dependencies> <dependency> <groupId>org.springframework.data ...
- Python传递参数的多种方式
Python中根据函数的输入参数以及是否有返回值可分为四种函数: 1.无参数无返回值 2.有参数无返回值 3.无参数有返回值 4.有参数无返回值 Python 中参数传递有下列五种方式; 1.位置传递 ...