在形式上,复合模式确实是多个模式的组合,但满足了这一条并不一定是复合模式,注意它的定义:将多个模式结合起来形成一个“框架”,以解决一般性问题。一提到“框架”,可能最容易联想到的就是MVC吧,不过MVC确实是一个经典的复合模式。
首先要创建一群呱呱叫的鸭子类,让他们实现接口Quackable:
public interface Quackable {
public void quack();
}
这是一个鸭子类:
public class RedheadDuck implements Quackable {
@Override
public void quack() {
System.out.println("Quack");
}
这时候水里还有鹅,也会叫:
public class Goose {
public void hoke(){
System.out.println("Honk");
}
}
想让鹅也实现Quackable接口统一管理,可以用适配器模式:
public class GooseAdapter implements Quackable {
Goose goose;
public GooseAdapter(Goose goose){
this.goose = goose;
observable = new Observable(this);
}
@Override
public void quack() {
goose.hoke();
notifyObservers();
}
这时,想要统计他们叫的次数,就可以使用装饰者模式把它们装饰城=成QuackCounter:
public class QuackCounter implements Quackable {
Quackable duck;
static int numberOfQuacks;
public QuackCounter(Quackable duck){
this.duck = duck;
}
@Override
public void quack() {
duck.quack();
numberOfQuacks++;
}
public static int getQuacks(){
return numberOfQuacks;
}
}
每次创建鸭子都要new很麻烦,就可以用工厂模式,要鸭子就直接跟工厂要:
public class CountingDuckFactory extends AbstrctDuckFactory {
@Override
public Quackable createMallardDuck() {
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 Flock implements Quackable {
ArrayList quackers = new ArrayList();
public void add(Quackable quacker){
quackers.add(quacker);
}
@Override
public void quack() {
Iterator iterator = quackers.iterator();
while (iterator.hasNext()){
Quackable quacker = (Quackable) iterator.next();
quacker.quack();
}
}
}
现在,生物学家想每次呱呱叫都被通知到,就可以使用观察者模式:
public class Flock implements Quackable {
ArrayList quackers = new ArrayList();
public void add(Quackable quacker){
quackers.add(quacker);
}
@Override
public void quack() {
Iterator iterator = quackers.iterator();
while (iterator.hasNext()){
Quackable quacker = (Quackable) iterator.next();
quacker.quack();
}
}
@Override
public void registerObserver(Observer observer) {
Iterator iterator = quackers.iterator();
while (iterator.hasNext()) {
Quackable duck = (Quackable) iterator.next();
duck.registerObserver(observer);
}
}
@Override
public void notifyObservers() {
}
}
测试类
public class DuckSimulator {
public static void main(String[] args) {
DuckSimulator simulator = new DuckSimulator();
AbstrctDuckFactory duckFactory = new CountingDuckFactory();
simulator.simulate(duckFactory);
}
void simulate(AbstrctDuckFactory duckFactory){
Quackable redheadDuck = duckFactory.createRedheadDuck();
Quackable duckCall = duckFactory.createDuckCall();
Quackable rubberDuck = duckFactory.createRubberDuck();
Quackable gooseDuck = new QuackCounter(new GooseAdapter(new Goose()));
System.out.println("\nDuck Simulator: With Composite - Flocks");
Flock flock = new Flock();
flock.add(redheadDuck);
flock.add(rubberDuck);
flock.add(duckCall);
flock.add(gooseDuck);
Flock flock1 = new Flock();
Quackable mallardDuck1 = duckFactory.createMallardDuck();
Quackable mallardDuck2 = duckFactory.createMallardDuck();
Quackable mallardDuck3 = duckFactory.createMallardDuck();
Quackable mallardDuck4 = duckFactory.createMallardDuck();
flock1.add(mallardDuck1);
flock1.add(mallardDuck2);
flock1.add(mallardDuck3);
flock1.add(mallardDuck4);
flock.add(flock1);
System.out.println("\nDuck Simulator: Whole Flock Simulation");
simulate(flock);
System.out.println("\nDuck Simulator: Mallard Flock Simulation");
simulate(flock1);
Quackologist quackologist = new Quackologist();
flock.registerObserver(quackologist);
simulate(flock);
System.out.println("The duck quacked "+QuackCounter.getQuacks()+" times");
}
void simulate(Quackable duck){
duck.quack();
}
}
结构:
模型:模型持有所有的数据、状态和程序逻辑,模型没有注意到视图和控制器,虽然它提供了操纵和检索状态的接口,并发送状态改变通知给观察者。是程序主体,代表了业务数据和业务逻辑。
视图:用来呈现模型,视图通常直接从模型中取得它需要显示的状态与数据。是与用户交互的界面,显示数据、接收输入,但不参与实际业务逻辑
控制器:取得用户的输入并解读其对模型的意思。接收用户输入,并解析反馈给Model。
MVC的最大优点就是把表现层View与模型Model分离,实现了设计上的松耦合(应对变化)以及代码的复用(View可以随便换,只需要改改新View里面那一丁点儿控制逻辑就好了)
前面说过了MVC是一种复合模式,那它到底复合了哪些模式,一起看看:
视图和控制器实现了策略模式:视图是一个对象,可以被调整使用不同的策略,而控制提供了策略。视图只关心系统中可视的部分,对与任何界面行为,都委托给控制器处理。使用策略模式也可以让视图和模型之间关系解耦,因为控制器负责和模型交互来传递用户的请求。对与工作是怎么完成的,视图豪不知情。
模型实现了观察者模式,当状态改变时,相关对象将持续更新。使用观察者模式,可以让模型完全独立于视图和控制器。同一个模型可以使用不同的视图,甚至可以同时使用多个视图。
显示包括了窗口、面板、按钮、文本标签等。每个显示组件如果不是组合节点(例如窗口),就是叶节点(例如按钮)。当控制器告诉视图更新时,只需告诉视图最顶层的组件即可,组合会处理其余的事。
MVC应用了多个模式,并能够较好的解决设计上的一般性问题,所以被称为复合模式。