模式的组合使用
案例一:小鸭子
这里仍然使用书中第一章的鸭子的案例。
首先创建一个“叫”的接口名为Quackable。所有的鸭子都实现这个接口。因为所有的鸭子都能叫。
public interface Quackable{
public void quack();
}
然后我们所有的鸭子,只要能叫,就都要实现这个接口:
/* MallardDuck */
public class MallardDuck implements Quackable {
public void quack() {
System.out.println(“Quack”);
}
}
/* ReadheadDuck */
public class RedheadDuck implements Quackable {
public void quack() {
System.out.println(“Quack”);
}
}
public class RubberDuck implements Quackable {
public void quack() {
System.out.println("Squeak");
}
}
public class DuckCall implements Quackable {
public void quack() {
System.out.println("Kwak");
}
}
调用
这是最简单的,使用接口调用。
public class DuckSimulator {
public static void main(String[] args) {
DuckSimulator simulator = new DuckSimulator();
simulator.simulate();
}
void simulate() {
// 用接口接收。
Quackable mallardDuck = new MallardDuck();
Quackable redheadDuck = new RedheadDuck();
Quackable duckCall = new DuckCall();
Quackable rubberDuck = new RubberDuck();
System.out.println("\nDuck Simulator");
simulate(mallardDuck);
simulate(redheadDuck);
simulate(duckCall);
simulate(rubberDuck);
}
void simulate(Quackable duck) {
duck.quack();
}
}
1. Adapter
现在添加一个一个大白鹅的类Goose。
public class Goose {
public void honk() {
System.out.println("Honk");
}
}
显然,Goose类并没有实现Quackable
接口,因为Goose的叫声是“鹅鹅鹅饿鹅鹅鹅”而不是“嘎嘎嘎嘎嘎嘎嘎”
那么我们如何在实际调用中使用Quackable
接口来实现Goose的调用呢?
对的,写一个Adapter
public class GooseAdapter implements Quackable{
Goose goose;
public GooseAdapter(Goose goose) {
super();
this.goose = goose;
}
public void quack() {
goose.honk();
}
}
那么我们在调用的时候,就可以通过GooseAdapter
使用Quackable
来接收Goose咯!
Quackable gooseDuck = new GooseAdapter(new Goose());
gooseDuck.quack();
2. 装饰模式
现在要增加一个功能,我们想记录有多少个quack()
被调用,即数一数有多少只鸭子,不算刚才那只大白鹅!
怎么实现呢?显然我们需要一个计数器。这个计数器在每次quack()被调用的时候,就计数一次,还要排除混入的那只大白鹅。试试装饰者模式
public class QuackCounter implements Quackable {
Quackable duck;
static int numberOfQuacks; //静态变量。全局共享。
public QuackCounter(Quackable duck) {
this.duck = duck;
}
public void quack() {
duck.quack();
numberOfQuacks++;
}
public static int getQuacks() {
return numberOfQuacks;
}
}
这样,我们在调用的时候,先将鸭子们装饰一下,增添计数的功能,然后在使用Quackable
接口调用
void simulate() {
Quackable mallardDuck = new QuackCounter(new MallardDuck());
Quackable redheadDuck = new QuackCounter(new RedheadDuck());
Quackable duckCall = new QuackCounter(new DuckCall());
Quackable rubberDuck = new QuackCounter(new RubberDuck());
Quackable gooseDuck = new GooseAdapter(new Goose());
System.out.println("\nDuck Simulator");
simulate(mallardDuck);
simulate(redheadDuck);
simulate(duckCall);
simulate(rubberDuck);
simulate(gooseDuck);
//getQuacks()是一个静态方法
System.out.println(“The ducks quacked “ +
QuackCounter.getQuacks() + “ times”);
}
**注意:**装饰模式有一个问题,就是想要计数,必须将这个鸭子使用QuackCounter
来装饰,一旦哪个忘记了,就无法对这个进行计数了。
3. 工厂模式
工厂设计:
- 抽象父类
- 普通鸭子
- 被
QuackCounter
修饰的鸭子
public abstract class AbstractDuckFactory {
public abstract Quackable createMMallardDuck();
public abstract Quackable createRedheadDuck();
public abstract Quackable createDuckCall();
public abstract Quackable createRubberDuck();
}
/**
* 生产拥有计数功能的鸭子
*/
public class CountingDuckFactory extends AbstractDuckFactory{
@Override
public Quackable createMMallardDuck() {
return new QuackCounter(new MallardDuck());
}
@Override
public Quackable createRedheadDuck() {
return new QuackCounter(new RedheadDuck());
}
@Override
public Quackable createDuckCall() {
return new QuackCounter(new DuckCall());
}
@Override
public Quackable createRubberDuck() {
return new QuackCounter(new RubberDuck());
}
}
/**
* 生产没有计数功能的鸭子
*/
public class DuckFactory extends AbstractDuckFactory{
@Override
public Quackable createMMallardDuck() {
return new MallardDuck();
}
@Override
public Quackable createRedheadDuck() {
return new RedheadDuck();
}
@Override
public Quackable createDuckCall() {
return new DuckCall();
}
@Override
public Quackable createRubberDuck() {
return new RubberDuck();
}
}
我们的测试类可以这样写了:
先new一个工厂,然后使用工厂创建鸭子。鸭子是否能够计数,会根据工厂的不同而确定。
public class DuckSimulator {
public static void main(String[] args) {
DuckSimulator simulator = new DuckSimulator();
//这个工厂决定了创建的鸭子的功能是否被装饰
AbstractDuckFactory duckFactory = new CountingDuckFactory();
simulator.simulate(duckFactory);
}
void simulate(AbstractDuckFactory duckFactory) {
Quackable mallardDuck = duckFactory.createMallardDuck();
Quackable redheadDuck = duckFactory.createRedheadDuck();
Quackable duckCall = duckFactory.createDuckCall();
Quackable rubberDuck = duckFactory.createRubberDuck();
Quackable gooseDuck = new GooseAdapter(new Goose());
System.out.println("\nDuck Simulator: With Abstract Factory");
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();
}
}
4. Composite Pattern组合模式
我们在上面的simulate()
函数中,创建鸭子(实际上是创建Quackable)很不好管理。因为他们都是单独的实例。如何更好的管理他们呢?
把他们封装到一个类Flock中。
public class Flock implements Quackable{
List<Quackable> quackers = new ArrayList<>();
public void add(Quackable quacker) {
quackers.add(quacker);
}
@Override
public void quack() {
// 迭代器模式 当然可以for遍历
Iterator<Quackable> iterator = quackers.iterator();
while(iterator.hasNext()) {
Quackable quacker = (Quackable) iterator.next();
quacker.quack();
}
}
}
5. 观察者模式
现在可以同意管理这群鸭子了。但是又出现了新的需求,我们如何能够实时的跟踪某一个鸭子呢???
当然,我们可以尝试观察者模式
观察者模式简单来说,如果某个对象是被观察者,那么他需要维护一个观察他的对象的队列。当他发生变化时,要主动通知观察他的对象们。
首先我们定义一个被观察者的接口Observable
public interface QuackObservable {
public void registerObserver(Observer observer);
public void notifyObservers();
}
然后,修改我们的Quackable
,来继承QuackObservable
接口
public interface Quackable extends QuackObservable {
public void quack();
}
修改完,我们会发现报错了。因为我们值钱所有实现Quackable接口的类都需要添加QuackObservable的方法。
- 我们可以在每个实现了
Quackable
接口的类都实现registerObserver()
和void notifyObservers()
方法。 - 或者我们可以把
reisterObserver
和notifyObservers
包装的代码包装到另一个类Observable。然后在每个Quackable
的实现类都增加一个Observable的实例
public class MallardDuck implements Quackable{
Observable observable;
public MallardDuck() {
this.observable = new Observable();
}
public void quack() {
System.out.println("Quack");
}
@Override
public void registerObserver(Observer observer) {
observable.registerObserver(observer);
}
@Override
public void notifyObservers() {
observable.notifyObservers();
}
}
所有实现Quackable
接口的类都要这样修改。
然后我们设计一个观察者,名字叫Quackologist
public class Quackologist implements Observer{
@Override
public void update(QuackObserable duck) {
System.out.println("Quackologist:" + duck + "just quacked");
}
}
我们最终的使用方法:
void simulate(AbstractDuckFactory duckFactory) {
// create duck factories and ducks here
// create flocks here
System.out.println(“\nDuck Simulator: With Observer”);
Quackologist quackologist = new Quackologist();
flockOfDucks.registerObserver(quackologist);
simulate(flockOfDucks);
System.out.println(“\nThe ducks quacked “ +
QuackCounter.getQuacks() +
“ times”);
}
注意Flock的修改
public class Flock implements Quackable{
List<Quackable> quackers = new ArrayList<>();
public void add(Quackable quacker) {
quackers.add(quacker);
}
@Override
public void quack() {
Iterator<Quackable> iterator = quackers.iterator();
while(iterator.hasNext()) {
Quackable quacker = (Quackable) iterator.next();
quacker.quack();
}
}
@Override
public void registerObserver(CompoundPattern.Observer observer) {
for(Quackable it : quackers) {
it.registerObserver(observer);
}
}
@Override
public void notifyObservers() {
for(Quackable it : quackers) {
it.notifyObservers();
}
}
}