2008-04-01
设计模式学习之复合模式(1)
关键字: 设计模式使用模式最棒的方式,就是把他们从家里找出来同其他模式展开交互.你越多的使用模式就越容易发现他们一同现身在你的设计中,对于这些在设计中携手合作征服许多问题的模式,我们给了一个特别的名字:复合模式.但是我们将某些模式结合使用,并不代表这些模式就够资格称为复合模式.复合模式必须够一般性,适合解决许多问题才行.
我们将再次使用鸭子的例子来说明并学习,下一章我们会拜访一个真正的复合模式--MVC,没错,就是MVC.
1.首先,我们将创建一个Quackable接口
public interface Quackable {
//只做一件事:呱呱叫
public void quack();
}
2.现在,某些鸭子实现了Quackable接口
public class MallardDuck implements Quackable {
//绿头鸭子
public void quack() {
System.out.println("Quack");
}
}
public class RedheadDuck implements Quackable {
//红头鸭子
public void quack() {
System.out.println("Quack");
}
}
public class DuckCall implements Quackable {
//如果我们没有加入别的种类的鸭子,就不大好玩了
//鸭鸣器也会呱呱叫,虽然不十分像
public void quack() {
System.out.println("Kwak");
}
}
public class RubberDuck implements Quackable {
//橡皮鸭,声音其实是吱吱叫
public void quack() {
System.out.println("Squeak");
}
}
3.好了,我们有了鸭子,还需要一个模拟器,制造一个会产生鸭子,还要确认鸭子呱呱叫的模拟器
public class DuckSimulator {
public static void main(String[] args) {
//创建一个模拟器,调用simulate方法
DuckSimulator simulator = new DuckSimulator();
simulator.simulate();
}
void simulate() {
//每一种会呱呱叫的鸭子都有一份实例
Quackable mallardDuck = new MallardDuck();
Quackable redheadDuck = new RedheadDuck();
Quackable duckCall = new DuckCall();
Quackable rubberDuck = new RubberDuck();
//模拟每种鸭子
simulate(mallardDuck);
simulate(redheadDuck);
simulate(duckCall);
simulate(rubberDuck);
}
void simulate(Quackable duck) {
//重载了simulate方法来模拟一种鸭子,剩下的事让多态发挥它的魔法
duck.quack();
}
}
4.只要有水塘的地方,就大概会有鸭子和鹅,我们为这个模拟器设计一个鹅类
public class Goose {
//鹅的叫声是咯咯
public void honk() {
System.out.println("Honk");
}
}
5.我们需要鹅适配器,既然鹅不会呱呱叫,那么我们可以利用适配器将鹅适配成鸭子
public class GooseAdapter implements Quackable {
Goose goose;
//传入要适配的对象
public GooseAdapter(Goose goose) {
this.goose = goose;
}
//当调用quack时,会被委托到鹅的honk方法
public void quack() {
goose.honk();
}
}
6.现在,模拟器中也应该可以使用鹅了,我们需要做的就是创建goose对象,将它包装进适配器
public class DuckSimulator {
public static void main(String[] args) {
//创建一个模拟器,调用simulate方法
DuckSimulator simulator = new DuckSimulator();
simulator.simulate();
}
void simulate() {
//每一种会呱呱叫的鸭子都有一份实例
Quackable mallardDuck = new MallardDuck();
Quackable redheadDuck = new RedheadDuck();
Quackable duckCall = new DuckCall();
Quackable rubberDuck = new RubberDuck();
//通过把goose包装进gooseAdapter,我们就可以让鹅像鸭子一样
Quackable gooseDuck = new GooseAdapter(new Goose());
//模拟每种鸭子
simulate(mallardDuck);
simulate(redheadDuck);
simulate(duckCall);
simulate(rubberDuck);
//一旦鹅被包装进来,我们就可以把它当做其他鸭子的Quackable对象
simulate(gooseDuck);
}
void simulate(Quackable duck) {
//重载了simulate方法来模拟一种鸭子,剩下的事让多态发挥它的魔法
duck.quack();
}
}
7.测试一下上面的DuckSimulator,你会发现,鹅和其他鸭子一起叫.现在我们考虑一下,我们如何在不变化鸭子类的情况下,计算呱呱叫的次数呢?有什么模式可以解决这个问题?
8.让我们创建一个装饰者,通过把鸭子包装进装饰者对象,给鸭子一些新行为(计算次数),我们不必修改鸭子的代码
//QuackCounter是一个装饰者,像适配器一样实现Quackable
public class QuackCounter implements Quackable {
//我们用一个实例变量来记录被装饰的呱呱叫对象
Quackable duck;
//用静态变量跟踪所有呱呱叫次数
static int numberOfQuacks;
public QuackCounter(Quackable duck) {
this.duck = duck;
}
//当quack被调用时,我们就把调用委托给正在装饰的Quackable对象,然后把叫声的次数加一
public void quack() {
duck.quack();
numberOfQuacks++;
}
//给装饰者加入一个静态方法,以便返回在所有Quackable中发生的叫声次数
public static int getQuacks() {
return numberOfQuacks;
}
}9.现在我们必须包装在QuackCounter装饰折中被实例化的每个Quackable对象,如果不这么做,鸭子会到处乱跑而使得我们无法统计叫声次数,我们需要更新模拟器,以便创建被装饰的鸭子
public class DuckSimulator {
public static void main(String[] args) {
DuckSimulator simulator = new DuckSimulator();
simulator.simulate();
}
void simulate() {
//每次我们创建一个Quackable,就用一个新的装饰者包装它
Quackable mallardDuck = new QuackCounter(new MallardDuck());
Quackable redheadDuck = new QuackCounter(new RedheadDuck());
Quackable duckCall = new QuackCounter(new DuckDuck());
Quackable rubberDuck = new QuackCounter(new RubberDuck());
//鹅不是呱呱叫,所以不用包装
Quackable gooseDuck = new DooseAdapter(new Goose());
//模拟每种鸭子
simulate(mallardDuck);
simulate(redheadDuck);
simulate(duckCall);
simulate(rubberDuck);
simulate(gooseDuck);
//就是在这里,我们收集呱呱叫行为
System.out.println("The ducks quacked "+QuackCounter.getQuacks()+" times");
}
void simulate(Quackable duck) {
duck.quack();
}
}
未完待续......
-------------->设计模式学习之复合模式(2)
发表评论
- 浏览: 20851 次
- 性别:

- 来自: 北京

- 详细资料
搜索本博客
我的相册
P1080256
共 30 张
共 30 张
最近加入圈子
最新评论
-
使用iBatis的自动化代码生 ...
有没有根据类生产数据库和xml的?
-- by aninfeel -
使用iBatis的自动化代码生 ...
IBatis去除注释版 http://hugh-lin.javaeye.com/ ...
-- by hugh-lin -
使用iBatis的自动化代码生 ...
我的不能用啊,郁闷掉了,真的是很黄很暴力。
-- by horror -
搭建Cloud Computing测试 ...
to fredzhang : 呵呵,我只是说用hadoop/hbase来搭 ...
-- by blank -
搭建Cloud Computing测试 ...
1. gfs的论文你仔细阅读过了吗?它的思想决定了基于它应当如何来实现,如何才能 ...
-- by fredzhang






评论排行榜