Head First 设计模式--1策略模式 组合优于继承
策略模式:第一了算法族,分别封装起来,让他们之间可以互相替换,次模式让算法的变化独立于使用算法的客户。
首先看个错误的面向对象。
假如我们需要写一个关于鸭子的程序,各种类型的鸭子。第一想到的就是建一个Duck接口,然后各种鸭子实现这个接口。
interface Duck{
public void quack();
} class MiniDuck implements Duck{
@Override
public void quack() {
//........
}
}
但是如果突然有一天,有个新需求,要有一个会飞的鸭子。那么炸了,在Duck上添加一个fly方法,所有的实现类都需要重写这个方法,如果真的有这个耐心把所有的类上都添加了一个新的方法,但是之前的测试你还需要重新一个一个的测试。确定要这么干。这时也许会想到另外一个方法,不在Duck上添加,只需要在会飞的那类鸭子中添加一个方法。如果你这么想,当初设计这个Duck接口干什么。直接写每个类啊,如果真的就这么干了,假如某个某个方法中,传入的参数只需要一个鸭子,不管什么类型的鸭子。要怎么处理。。。
经过上面这么一想,Duck是一定要有的,这时的想法会是在创建两个接口,一个Flyable接口,一个Quackable接口,这两个接口分别有fly和quack方法,Duck中有自己的方法。如果这么弄,那么每个鸭子首先要实现Duck接口,其次,根据具体功能在判断需不需要集成另外两个接口。你感觉这样真的好?如果感觉还可以接受,突然有一天,大多数的鸭子又有了一个查看颜色的方法。你需要在写第三个接口来让实现类鸭子实现。40个类同时实现这个接口,想一想工作量。
设计原则:找到应用中可能要变化之处,把他们独立出来,不要和那些不变的代码混在一起。
这里我们知道鸭子的飞和叫是变化的,就把这两部分抽出来,让他们远离鸭子类。设计两组类处理飞和叫。
设计原则:针对接口编程而不是针对实现编程。(这里所说的针对接口编程指的是针对超类,关键在于利用多态,接口并不一定是interface,可以在没有interface的情况下“针对接口编程”,只是一般来说我们用interface和abstract来当超类)
我们利用接口来代表每个行为,创建一个FlyBehavior和一个QuackBehavior,行为的每个实现都将实现上面的接口,而不是由Duck类来实现上面的接口。原来的时候,行为由Duck超类来实现或由子类具体实现。这两种做法都是依赖于实现。而现在的实现是在每个接口的子类,不会绑定在Duck身上。
直接看代码
interface FlyBehavior {
public void fly();
} class FlyWithWings implements FlyBehavior {
@Override
public void fly() {
System.out.println("i am flying");
}
} class FlyNoWay implements FlyBehavior {
@Override
public void fly() {
System.out.println("i can not fly");
}
} interface QuackBehabior {
public void quack();
} class Quack implements QuackBehabior {
@Override
public void quack() {
System.out.println("Quack");
}
} class MuteQuack implements QuackBehabior {
@Override
public void quack() {
System.out.println("<< Silence >>");
}
} class Squeak implements QuackBehabior {
@Override
public void quack() {
System.out.println("Squeak");
}
} abstract class Duck {
FlyBehavior flyBehavior;
QuackBehabior quackBehabior; public void setFlyBehabior(FlyBehavior fb) {
this.flyBehavior = fb;
} public void setQuackBehavior(QuackBehabior qb) {
this.quackBehabior = qb;
} public Duck() {} public abstract void display(); public void performFly() {
flyBehavior.fly();
} public void performQuack() {
quackBehabior.quack();
} public void swim() {
System.out.println("all ducks float");
}
} class MallardDuck extends Duck {
public MallardDuck() {
quackBehabior = new Quack();
flyBehavior = new FlyWithWings();
} @Override
public void display() {
System.out.println("i am a Mallard duck");
}
}
类图:
这里Duck是不是应该也设计成接口?这个要根据自己具体的程序来定,在这个程序中,并不需要,让Duck成为一个具体类可以让继承的子类与Duck具有相同的属性和方法,比如swim方法,不用每个继承类在去重写swim方法,游泳都是一样的游泳。
这里的设计模式就是用到的策略模式,如果想动态的设置鸭子的飞行方式,在运行时,只要设置一个对应的FlyBehavior即可。
设计原则:多用组合,少用继承
Head First 设计模式--1策略模式 组合优于继承的更多相关文章
- HeadFirst设计模式之策略模式
什么是策略模式:它定义了一系列算法,可以根据不同的实现调用不同的算法 大多数的设计模式都是为了解决系统中变化部分的问题 一.OO基础 抽象.封装.多态.继承 二.OO原则 1.封装变化,如把FlyBe ...
- PHP设计模式之策略模式
前提: 在软件开发中也常常遇到类似的情况,实现某一个功能有多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能.如查 找.排序等,一种常用的方法是硬编码(Hard Cod ...
- JavaScript设计模式之策略模式(学习笔记)
在网上搜索“为什么MVC不是一种设计模式呢?”其中有解答:MVC其实是三个经典设计模式的演变:观察者模式(Observer).策略模式(Strategy).组合模式(Composite).所以我今天选 ...
- [design-patterns]设计模式之一策略模式
设计模式 从今天开始开启设计模式专栏,我会系统的分析和总结每一个设计模式以及应用场景.那么首先,什么是设计模式呢,作为一个软件开发人员,程序人人都会写,但是写出一款逻辑清晰,扩展性强,可维护的程序就不 ...
- python设计模式之策略模式
每次看到项目中存在大量的if else代码时,都会心生一丝不安全感. 特别是产品给的需求需要添加或者更改一种if条件时,生怕会因为自己的疏忽而使代码天崩地裂,哈哈,本文的目的就是来解决这种不安全感的, ...
- 设计模式:策略模式(Strategy)
定 义:它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化, 不会影响到使用算法的客户. 示例:商场收银系统,实现正常收费.满300返100.打8折.......等不同收费 ...
- 乐在其中设计模式(C#) - 策略模式(Strategy Pattern)
原文:乐在其中设计模式(C#) - 策略模式(Strategy Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 策略模式(Strategy Pattern) 作者:webabc ...
- JavaScript设计模式之策略模式
所谓"条条道路通罗马",在现实中,为达到某种目的往往不是只有一种方法.比如挣钱养家:可以做点小生意,可以打分工,甚至还可以是偷.抢.赌等等各种手段.在程序语言设计中,也会遇到这种类 ...
- 【设计模式】【应用】使用模板方法设计模式、策略模式 处理DAO中的增删改查
原文:使用模板方法设计模式.策略模式 处理DAO中的增删改查 关于模板模式和策略模式参考前面的文章. 分析 在dao中,我们经常要做增删改查操作,如果每个对每个业务对象的操作都写一遍,代码量非常庞大. ...
随机推荐
- VMware安装Linux第一天
今天上午下载了VMware-workstation_full_12.1.1.6932,它的Key是5A02H-AU243-TZJ49-GTC7K-3C61N,这些都是网络上搜罗到的. VMWare安装 ...
- 从零开始学Linux[一]:基本命令:系统信息、目录、文件、文件编辑
摘要:linux基础学习:系统信息.目录.文件查找.文件操作.查看文件内容及大小.软链接.VIM使用. 现在Linux的使用非常普遍.对于一个小白来说,满屏幕的字母,看起来就是一头雾水~ 目前由于 ...
- Gulp入门教程(转载)
本人转载自: Gulp入门教程
- paper 94:视觉领域博客资源1之中国部分
这是收录的图像视觉领域的博客资源的第一部分,包含:中国内地.香港.台湾 这些名人大家一般都熟悉,本文仅收录了包含较多资料的个人博客,并且有不少更新,还有些名人由于分享的paper.code或者数据集不 ...
- Roll A Ball
GameObject的添加就不细说了,地面,小球和碰撞小物体. 刚体组件(Rigidbody): 使物体能够模拟物理效果,比如重力,碰撞,推力等: 控制小球移动的脚本(Script,Ball的脚本): ...
- Struts2 配置详解
1. web.xml 此文件的配置可以参看struts2的示例文档 <filter> <filter-name>struts2</filter-name> < ...
- CSS:opacity 的取值范围是 0~1
CSS:opacity 的取值范围是 0~1,难怪设置为 1~100 看不到效果.
- Markdown--PDF--PPT--Flash 工具链
markdown->html Haroopad / sublime->pdf chrome ctrl+p 打印成无边框pdf->ppt PDF to PowerPoint Conve ...
- QTP
QTP支持功能测试和回归测试的自动化. 支持录制功能,可以对脚本设置检查点,也可以进行参数化.可以在一个ACTION中调用另外一个ACTION action可以调用外部脚本.可以复制已有的ACTION ...
- Linux之保留yum安装软件后的RPM包
yum安装软件很方便,但是下载下来的rpm包在安装后默认会被删除掉: 如果希望保留yum安装的软件包该如何做呢? 设置方法: 将/etc/yum.conf里对应的keepcache参数改为1即可,然后 ...