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中,我们经常要做增删改查操作,如果每个对每个业务对象的操作都写一遍,代码量非常庞大. ...
随机推荐
- 关于ios8模拟器不能输入中文问题以及软键盘不弹出问题
在Xcode菜单栏中 Product->scheme->Edit Scheme->Options->Application Region改为中国,就可以输入中文了, 如果软 ...
- javascript对json对象的序列化与反序列化
首先引入一个json2.js.官方的地址为:https://github.com/douglascrockford/JSON-js 这里为了方便我直接贴上源代码 /* json2.js 2013-05 ...
- 刨根问底U3D---如何退出Play模式后保留数据更改
实际中遇到的需求 在做一款对抗类游戏,目前正在调整游戏的平衡性 所以就产生了一个需求 希望可以在Play模式时候对数据源做的更改可以在退出时候被保存下来. 举个Case, 比如 有一个炮塔 可以发射子 ...
- java栈与堆
java基本类型: 变量存放在栈区 java引用类型: 变量名存放在栈区,变量内容存放在堆区. 实例一: int a = 6; int b = 9; swap(int x, int y) { int ...
- SSH三大框架的工作原理及流程
Hibernate工作原理及为什么要用? 原理:1.通过Configuration().configure();读取并解析hibernate.cfg.xml配置文件2.由hibernate.cfg.x ...
- 创建和导出SVG的技巧(转载)
本文转载自: 创建和导出SVG的技巧
- 【001:转载 eclipse中颜色的设置】
转自于:http://www.cnblogs.com/arci/archive/2011/01/23/1942646.html Eclipse颜色设置 参考配色方案: http://www.cs.cm ...
- word转html方法
在网上看了一篇关于word转html的文章,感觉不错,和大家分享一下. /// <summary> /// word转成html /// </summary> /// < ...
- 动态的计算行高 加载数据源 有多少显示多少 tableView 包含 colloctionView 显示复杂的界面写法
有时候,我们经常碰到这样的需求 先遵守代理 @interface PublishCollectionCell ()<UICollectionViewDataSource, UICollectio ...
- PHP中怎样创建一个空对象?
如果没有声明一个对象然后就对其属性赋值会出现警告.那么我们给它创建一个空对象然后赋值就好了.PHP中创建一个空对象代码如下: 第一种方式: $empty_object = new stdClass() ...