设计模式学习之复合模式(2)
关键字: 设计模式接上篇------>设计模式学习之复合模式(1)
我们为什么不将创建鸭子的程序集中在一个地方呢?换句话说,让我们将创建和装饰的部分包装起来,这看起来像是什么模式?
10.我们需要一些质量控制来确保鸭子一定是被包装起来的,需要建造一个工厂创建装饰过的鸭子.此工厂应该生产各种不同类型的鸭子的产品家族,使用我们使用抽象工厂模式.
//定义一个抽象工厂,它的子类会创建不同的家族
public abstract class AbstractDuckFactory {
//每个方法创建一种鸭子
public abstract Quackable createMallardDuck();
public abstract Quackable createRedheadDuck();
public abstract Quackable createDuckCall();
public abstract Quackable createRubberDuck();
}
//创建一个工厂,此工厂创建没有装饰者的鸭子
public class DuckFactory extends AbstractDuckFactory {
//每个方法创建一个产品,一种特定种类的Quackable.
//模拟器并不知道实际的产品是什么,只知道它实现了Quackable接口
public Quackable createMallardDuck() {
return new MallardDuck();
}
public Quackable createRedheadDuck() {
return new RedheadDuck();
}
public Quackable createDuckCall() {
return new DuckCall();
}
public Quackable createRubberDuck() {
return new RubberDuck();
}
}
//现在,要创建我们真正需要的工厂
public class CountingDuckFactory extends AbstractDuckFactory {
//每个方法都会先用叫声计数装饰者将Quackable包装进来.模拟器并不知道有何不同,
//只知道它实现了Quackable接口,所有的叫声都会被计算进去
public Quackable createMallardDuck() {
return new QuackCounter(new MallardDuck());
}
public Quackable createRedheadDuck() {
return new QuackCounter(new RedheadDuck());
}
public Quackable createDuckCall() {
return new QuackCounter(new DuckCall());
}
public Quackable createRubberDuck() {
return new QuackCounter(new RubberDuck());
}
}
11.我们修改模拟器来使用这个工厂
public class DuckSimulator {
public static void main(String[] args) {
DuckSimulator simulator = new DuckSimulator();
//首先我们创建工厂,准备把它传入simulate方法
AbstractDuckFactory duckFactory = new CountingDuckFactory();
simulator.simulate(duckFactory);
}
//simulate需要一个AbstractDuckFactory参数,利用它来创建鸭子,而不是直接实例化鸭子
void simulate(AbstractDuckFactory duckFactory) {
Quackable redheadDuck = duckFactory.createMallardDuck();
Quackable redheadDuck = duckFactory.createRedheadDuck();
Quackable duckCall = duckFactory.createDuckCall();
Quackable rubberDuck = duckFactory.createRubberDuck();
Quackable gooseDuck = new GooseAdapter(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();
}
}
测试...
看到这里,你不觉得分别管理这些不同的鸭子变得有些困难吗?有什么办法帮我们作为一个整体来管理这些鸭子,甚至让我们管理几个想持续追踪的鸭子家族吗?下一次命令就能够让整个集合的鸭子听命行事,什么模式可以帮我们?
还记得吗,组合模式允许我们像对待单个对象一样对待对象集合.
12.让我们创建一群鸭子,实际上是一群Quackable
//别忘了,组合需要和叶节点元素一样实现相同的接口,这里的叶节点就是'Quackable'
public class Flock implements Quackable {
//在每个flock内,我们使用ArrayList记录属于这个flock的Quackable对象
ArrayList quackers = new ArrayList();
//用add方法新增Quackable对象到flock
public void add(Quackable quacker) {
quackers.add(quacker);
}
//注意到了吗,这里我们其实还使用了迭代器模式
public void quack() {
Iterator iterator = quackers.iterator();
while (iterator.hasNext()) {
Quackable quacker = (Quackable)iterator.next();
//毕竟flock也是Quackable,所以也要具备quack方法,此方法会对整群产生作用
//我们遍历ArrayList调用每个元素上的quack方法
quacker.quack();
}
}
}
13.我们的组合已经准备好了,我们需要一些让鸭子能进入组合的代码,再来修改模拟器
public class DuckSimulator {
public static void main(String[] args) {
DuckSimulator simulator = new DuckSimulator();
//首先我们创建工厂,准备把它传入simulate方法
AbstractDuckFactory duckFactory = new CountingDuckFactory();
simulator.simulate(duckFactory);
}
//simulate需要一个AbstractDuckFactory参数,利用它来创建鸭子,而不是直接实例化鸭子
void simulate(AbstractDuckFactory duckFactory) {
Quackable redheadDuck = duckFactory.createRedheadDuck();
Quackable duckCall = duckFactory.createDuckCall();
Quackable rubberDuck = duckFactory.createRubberDuck();
Quackable gooseDuck = new GooseAdapter(new Goose());
//我们先创建一个flock,然后把许多Quackable塞给它,这个flock是主群
Flock flockOfDucks = new Flock();
flockOfDucks.add(redheadDuck);
flockOfDucks.add(duckCall);
flockOfDucks.add(rubberDuck);
flockOfDucks.add(gooseDuck);
//然后创建一个新的绿头鸭群
Flock flockOfMallards = new Flock();
//创建绿头小家族
Quackable mallardOne = duckFactory.createMallardDuck();
Quackable mallardTwo = duckFactory.createMallardDuck();
Quackable mallardThree = duckFactory.createMallardDuck();
Quackable mallardFour = duckFactory.createMallardDuck();
//将刚创建的绿头小家族加入绿头鸭群
flockOfMallards.add(mallardOne);
flockOfMallards.add(mallardTwo);
flockOfMallards.add(mallardThree);
flockOfMallards.add(mallardFour);
//将绿头鸭群加入主群
flockOfDucks.add(flockOfMallards);
//测试整群
simulate(flockOfDucks);
//只测试绿头鸭群
simulate(flockOfMallards);
//最后显示呱呱叫次数
System.out.println("\nThe ducks quacked " +
QuackCounter.getQuacks() +
" times");
}
//这里不需要修改,因为flock也是Quackable
void simulate(Quackable duck) {
duck.quack();
}
}
14.既然我们有办法管理整群鸭子,我们也应该有办法来追踪个别的鸭子及其实时呱呱叫行为,我想到起了有个模式可以观察对象的行为:观察者模式
首先我们需要一个Observable接口,所谓Observable就是被观察的对象,Observable需要注册和通知观察者的方法.
//如何想被观察的Quackable都必须实现QuackObservable接口
public interface QuackObservable {
//注册观察者,任何实现了Observer接口的对象都可以监听呱呱叫
public void registerObserver(Observer observer);
//通知观察者
public void notifyObservers();
}
//现在我们需要确定所有的Quackable都实现此接口,所以干脆我们让Quackable扩展此接口
public interface Quackable extends QuackObservable {
public void quack();
}15.现在我们必须确定所有实现Quackable的具体类都能够扮演QuackObservable的角色.每一个类中都需要实现注册和通知,使用另外的做法:我们要在另一个Observalbe的类中封装注册和通知,然后将它和QuackObservable组合在一起,这样,我们只需要一份代码即可,QuackObservable所有的调用都委托给Observable辅助类
//Observable必须实现QuackObservable,因为他们具有一组相同的方法,
//QuackObservable会将这些方法的调用转给Observable的方法
public class Observable implements QuackObservable {
ArrayList observers = new ArrayList();
QuackObservable duck;
//在次构造器中我们传进了QuackObservable.看看notifyObservers方法,
//你会发现当通知发生时,观察者把次对象传进去.好让观察者知道是哪个对象在呱呱叫
public Observable(QuackObservable duck) {
this.duck = duck;
}
//注册
public void registerObserver(Observer observer) {
observers.add(observer);
}
//通知
public void notifyObservers() {
Iterator iterator = observers.iterator();
while (iterator.hasNext()) {
Observer observer = (Observer)iterator.next();
observer.update(duck);
}
}
public Iterator getObservers() {
return observers.iterator();
}
}
16.整合Observable辅助类和Quackable类
public class MallardDuck implements Quackable {
//每个Quackable都有一个Observable实例变量,在构造器中传入一个MallardDuck对象的引用
Observable observable;
public MallardDuck() {
observable = new Observable(this);
}
public void quack() {
System.out.println("Quack");
//当呱呱叫时,需要让观察者知道
notifyObservers();
}
//这是两个QuackObservable方法,注意我们只是委托给辅助类进行
public void registerObserver(Observer observer) {
observable.registerObserver(observer);
}
public void notifyObservers() {
observable.notifyObservers();
}
}
17.我们已经实现了Observable所需要的一切,现在需要一些观察者Observer
//Observer只有一个update方法,他需要传入一个正在呱呱叫的对象QuackObservable
public interface Observer {
public void update(QuackObservable duck);
}
//我们需要实现Observer,否则无法以QuackObservable注册
public class Quackologist implements Observer {
//打印出正在呱呱叫的Quackable对象
public void update(QuackObservable duck) {
System.out.println("Quackologist: " + duck + " just quacked.");
}
}
18.我们准备开始观察了,让我们更新模拟器,了解这一切是如何工作的
public class DuckSimulator {
public static void main(String[] args) {
DuckSimulator simulator = new DuckSimulator();
AbstractDuckFactory duckFactory = new CountingDuckFactory();
simulator.simulate(duckFactory);
}
void simulate(AbstractDuckFactory duckFactory) {
//other 创建鸭子工厂和鸭子
//other 创建群
//我们在这里所需要做的就是创建一个Quackologist,把它注册成为一个群的观察者
Quackologist quackologist = new Quackologist();
flockOfDucks.registerObserver(quackologist);
simulate(flockOfDucks);
System.out.println("\nThe ducks quacked " +
QuackCounter.getQuacks() +
" times");
}
void simulate(Quackable duck) {
duck.quack();
}
}如果想观察整个群呢?有什么办法?考虑试写一下
未完待续...
发表评论
- 浏览: 20847 次
- 性别:

- 来自: 北京

- 详细资料
搜索本博客
我的相册
共 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






评论排行榜