Fork me on GitHub

设计模式之复合模式

设计模式之复合模式

1. 什么是复合模式

在形式上,复合模式确实是多个模式的组合,但满足了这一条并不一定是复合模式,注意它的定义:将多个模式结合起来形成一个“框架”,以解决一般性问题。一提到“框架”,可能最容易联想到的就是MVC吧,不过MVC确实是一个经典的复合模式。

2. 具体实例

项目的类图:

1

首先要创建一群呱呱叫的鸭子类,让他们实现接口Quackable:

1
2
3
public interface Quackable {
public void quack();
}

这是一个鸭子类:

1
2
3
4
5
public class RedheadDuck implements Quackable {
@Override
public void quack() {
System.out.println("Quack");
}

这时候水里还有鹅,也会叫:

1
2
3
4
5
6
public class Goose {

public void hoke(){
System.out.println("Honk");
}
}

想让鹅也实现Quackable接口统一管理,可以用适配器模式:

1
2
3
4
5
6
7
8
9
10
11
12
13
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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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很麻烦,就可以用工厂模式,要鸭子就直接跟工厂要:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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());
}
}

因为鸭子太多了,可以用组合模式统一管理,用迭代器模式查看内部对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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();
}
}
}

现在,生物学家想每次呱呱叫都被通知到,就可以使用观察者模式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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() {

}
}

测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
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();
}
}

3. MVC与复合模式

结构

  • 模型:模型持有所有的数据、状态和程序逻辑,模型没有注意到视图和控制器,虽然它提供了操纵和检索状态的接口,并发送状态改变通知给观察者。是程序主体,代表了业务数据和业务逻辑。
  • 视图:用来呈现模型,视图通常直接从模型中取得它需要显示的状态与数据。是与用户交互的界面,显示数据、接收输入,但不参与实际业务逻辑
  • 控制器:取得用户的输入并解读其对模型的意思。接收用户输入,并解析反馈给Model。

2

MVC的最大优点就是把表现层View与模型Model分离,实现了设计上的松耦合(应对变化)以及代码的复用(View可以随便换,只需要改改新View里面那一丁点儿控制逻辑就好了)

前面说过了MVC是一种复合模式,那它到底复合了哪些模式,一起看看:

  1. 策略模式

视图和控制器实现了策略模式:视图是一个对象,可以被调整使用不同的策略,而控制提供了策略。视图只关心系统中可视的部分,对与任何界面行为,都委托给控制器处理。使用策略模式也可以让视图和模型之间关系解耦,因为控制器负责和模型交互来传递用户的请求。对与工作是怎么完成的,视图豪不知情。

  1. 观察者模式

模型实现了观察者模式,当状态改变时,相关对象将持续更新。使用观察者模式,可以让模型完全独立于视图和控制器。同一个模型可以使用不同的视图,甚至可以同时使用多个视图。

  1. 组合模式

显示包括了窗口、面板、按钮、文本标签等。每个显示组件如果不是组合节点(例如窗口),就是叶节点(例如按钮)。当控制器告诉视图更新时,只需告诉视图最顶层的组件即可,组合会处理其余的事。

MVC应用了多个模式,并能够较好的解决设计上的一般性问题,所以被称为复合模式。

本文标题:设计模式之复合模式

文章作者:WilsonSong

发布时间:2018年10月17日 - 09:10

最后更新:2018年10月17日 - 09:10

原始链接:https://songwell1024.github.io/2018/10/17/compoundMode/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

-------------本文结束感谢您的阅读-------------