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)

评论
发表评论

您还没有登录,请登录后发表评论

blank
搜索本博客
我的相册
5c2c51d9-1a15-3713-8084-e1742c808801-thumb
P1080256
共 30 张
存档
最新评论