11种行为型模式(上):模板、中介、命令、责任链、策略、迭代器

模板方法模式 Template

在模板方法中按照一定规则和顺序调用基本方法,将一些基本方法延迟到子类实现,抽象模板类中方法分为两种:

  1. 基本方法:由子类实现,在模板方法被调用。
  2. 模板方法:一个框架,实现对基本方法的调用,完成固定逻辑。为防止恶意操作,一般给模板方法加上 final 关键字,避免被覆写。

类图

使用场景

  1. 多个子类有公有的方法,并且逻辑基本相同。
  2. 重要、复杂的算法,可以把核心算法设计为模板方法,周边的相关细节功能则由各个子类实现。
  3. 重构时,模板方法模式经常使用,把相同代码抽取到父类,然后通过钩子函数(见扩展)约束其行为。

优点

  1. 封装不变部分,扩展可变部分。可通过继承来进行扩展。
  2. 提取公共部分代码,便于维护。
  3. 行为由父类控制,子类实现。符合开闭原则。

缺点

  1. 一般的设计习惯,抽象类负责声明最抽象、最一般的事物属性和方法,实现类完成具体的事物属性和方法。但是模板方法模式却颠倒了,抽象类定义的部分抽象方法由子类实现,导致子类执行的结果影响了父类的结果,也就是子类对父类产生了影响,在复杂项目中会带来代码阅读难度。

注意事项

  1. 父类调用子类的其他三种方式,但不建议父类调用子类!此时考虑使用模板方法模式。
    • 子类传递到父类的有参构造中,然后调用。
    • 使用反射的方式调用。
    • 父类调用子类的静态方法。
  2. 为防止恶意操作,一般给模板方法加上 final 关键字,避免被覆写。

扩展

  1. 外界通过钩子方法影响模板执行结果

代码演示

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
abstract class Car {
// 基本方法
protected void start() { System.out.println("打火启动"); }
protected abstract void drive();
protected void alarm() { System.out.println("鸣笛~~~"); }
protected void stop() { System.out.println("刹车停车"); }
// 模板方法
public final void run() {
System.out.println(this.getClass().getSimpleName() + "开动!------------");
start();
drive();
if (isAlarm()) {
alarm();
}
stop();
}
// 钩子函数
protected boolean isAlarm() { return true; }
}

class Model1 extends Car {
@Override
protected void drive() { System.out.println("前轮驱动"); }
}

class Model2 extends Car {
private boolean isAlarm;

public Model2(boolean isAlarm) { this.isAlarm = isAlarm; }

@Override
protected void drive() { System.out.println("后轮驱动"); }
@Override
protected boolean isAlarm() { return isAlarm; }
}

class Client {
public static void main(String[] args) {
Car m1 = new Model1();
m1.run();
Car m2 = new Model2(false);
m2.run();
}
}

中介者模式 Mediator

也叫调停者模式。每个类只负责处理自己的行为,与自己无关的交给中介者处理,包含以下几个部分:

  1. Mediator 抽象中介者

    抽象中介者角色定义统一的接口,用于各同事角色之间的通信。

  2. Concrete Mediator 具体中介者

    具体中介者角色通过协调各同事角色实现协作行为,因此它必须依赖各个同事角色。

  3. Colleague 同事类

    每个同事角色都知道中介者,而且与其他同事角色通信的时候,一定要通过中介者角色协作。每个同事类行为分为两种:一种是同事本身的行为,比如改变对象本身的状态,处理自己的行为等,这叫自发行为(Self-Method),与其他同事类或中介者没有任何联系;第二种是必须依赖中介者才能完成的行为,叫做依赖方法(Dep-Method)。

类图

使用场景

  1. N个对象之间紧密耦合的情况,这时一定要考虑使用中介者模式,把蛛网梳理为星型结构。(N > 2)

    紧密耦合的标准:在类图中出现了蜘蛛网状结构。

  2. 多个对象有依赖关系,但是依赖的行为尚不确定或者有发生改变的可能,此时建议使用中介者模式,降低变更引起的风险扩散。

  3. 产品开发。一个明显的例子就是 MVC 框架,把中介者模式应用到产品中,可以提升产品性能和扩展性。但是对于项目开发未必,因为项目是以交付投产为目标,而产品则是以稳定、高效、扩展为宗旨。

  4. 实际案例

    • 机场调度中心。调度各个飞机以及其他部门工作人员。

    • MVC 框架。其中的 controller 前端控制器就是中介者,作用是把 model 业务逻辑 和 view 视图隔离开。

    • 媒体网关。MSN 作为中介者接收张三发的消息,查找李四并发送消息,同时通知张三消息已发送。与此相反的是 IPMsg 飞鸽,直接使用 UDP 广播的方式,每个客户端同时也是服务端。

    • 中介服务。租房中介、出国中介。

优点

  1. 减少类间依赖,把原有的一对多依赖变成了一对一。同事类只依赖中介者,减少了依赖,同时也降低了类间的耦合。

缺点

  1. 中介者会膨胀较大,逻辑复杂,原本N个对象直接的相互依赖关系转换为中介者和同事类的依赖,同事类越多,中介者逻辑越复杂。

注意事项

  1. 中介者模式简单,但很容易被误用,类之间的依赖关系是必然存在的,不能只要看到有多个依赖关系就使用中介者模式,简单的几个对象依赖,如果为了使用模式而加入中介者,必然导致中介者逻辑复杂化而产生膨胀问题。关键点是以多个对象之间紧密耦合作为标准进行判断。
  2. 中介者模式很少用到接口或者抽象类,这与依赖倒置原则有冲突。原因在于同事类不是兄弟类,协作完成不同的任务,处理不同的业务,所以不能在抽象类或者接口中严格定义同事类必须具有的方法(这点可以看出继承是高侵入性的)。如果两个对象不能提炼出共性,那就不要刻意去追求两者的抽象,抽象只要定义出模式需要的角色即可。当然如果严格遵守面向接口编程,则需要抽象,这要在实际开发中灵活掌握。
  3. 一个中介者抽象类一般只有一个实现者,除非中介者逻辑非常复杂,代码量非常大。

代码演示

以进销存系统为例。

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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
public class mediatorPattern extends AbstractMediator {
@Override
public void execute(String str, Object... objects) {
if (str.equalsIgnoreCase("purchase.buy")) {
this.buyComputer((Integer) objects[0]);
} else if (str.equalsIgnoreCase("sale.sell")) {
this.sellComputer((Integer) objects[0]);
} else if (str.equalsIgnoreCase("sale.offsell")) {
this.offSell();
} else if (str.equalsIgnoreCase("stock.clear")) {
this.clearStock();
}
}

private void buyComputer(int num) {
int saleStatus = super.sale.getSaleStatus();
if (saleStatus > 80) {
System.out.println("销量不错,采购电脑" + num + "台");
super.stock.increase(num);
} else {
int buyNum = num / 2;
System.out.println("销量一般,折半采购电脑" + buyNum + "台");
}
}

private void sellComputer(int num) {
try {
super.stock.decrease(num);
} catch (Exception e) {
System.out.println("库存数量不足,需要进货" + num + "台");
super.purchase.buyComputer(num);
}
}

// 打折售卖
private void offSell() {
System.out.println("折价销售电脑" + stock.getStockNum() + "台");
}

// 清仓
private void clearStock() {
super.sale.offSale();
super.purchase.refuseBuyComputer();
}
}

// 抽象中介者
abstract class AbstractMediator {
protected Purchase purchase = new Purchase(this);
protected Sale sale = new Sale(this);
protected Stock stock = new Stock(this);
// 中介者最重要的事件方法,处理多个对象之间的关系
public abstract void execute(String str, Object... objects);
}


// 抽象同事类
abstract class AbstractColleague {
protected AbstractMediator mediator;
public AbstractColleague(AbstractMediator mediator) { this.mediator = mediator; }
}

// 进
class Purchase extends AbstractColleague {
public Purchase(AbstractMediator mediator) { super(mediator); }

public void buyComputer(int num) { super.mediator.execute("purchase.buy", num); }
public void refuseBuyComputer() { System.out.println("不再采购电脑"); }
}

// 销
class Sale extends AbstractColleague {
public Sale(AbstractMediator mediator) { super(mediator); }

// 销售电脑
public void sellComputer(int num) {
super.mediator.execute("sale.sell", num);
System.out.println("销售电脑" + num + "台");
}
// 反馈销售情况,0~100变化
public int getSaleStatus() {
Random random = new Random(System.currentTimeMillis());
int saleStatus = random.nextInt(100);
System.out.println("电脑销售状况:" + saleStatus);
return saleStatus;
}
// 折扣处理
public void offSale() {
super.mediator.execute("sale.offsell");
}

}

// 存
class Stock extends AbstractColleague {
private static int computerNum = 100;

public Stock(AbstractMediator mediator) { super(mediator); }

// 增加库存
public void increase(int num) {
computerNum += num;
System.out.println("增加" + num + "台电脑后,库存:" + computerNum);
}
// 减少库存
public void decrease(int num) throws Exception {
if (computerNum >= num) {
computerNum -= num;
System.out.println("减少" + num + "台电脑后,库存:" + computerNum);
} else {
throw new Exception("库存量不足");
}
}
// 获取库存数量
public int getStockNum() {
return computerNum;
}
// 清库存
public void clearStock() {
System.out.println("要清理的库存量:" + computerNum);
super.mediator.execute("stock.clear");
}
}

class Client {
public static void main(String[] args) {
AbstractMediator mediator = new mediatorPattern();
System.out.println("------------采购员采购电脑------------");
Purchase purchase = new Purchase(mediator);
purchase.buyComputer(10);
System.out.println("------------销售员销售电脑------------");
Sale sale = new Sale(mediator);
sale.sellComputer(200);
System.out.println("------------仓库管理员清库处理------------");
Stock stock = new Stock(mediator);
stock.clearStock();
}
}

命令模式 Command

高内聚模式。把请求方 Invoker 和 执行方 Receiver 分开了,主要角色有:

  1. Receiver 接受者:实现类执行具体命令。
  2. Command 命令角色:声明要执行的命令。
  3. Invoker 调用者:接收命令,执行命令。

类图

使用场景

  1. 在认为是命令的地方就可以采用。例如 GUI 开发中的一个按钮点击;模拟DOS命令;出发-反馈机制的处理。

优点

  1. 类间解耦。调用者与接收者之间没有任何依赖关系,调用者实现功能时只需调用 Command 抽象类的 execute(),不需要了解到底是哪个接收者执行。
  2. 可扩展性。Command 的子类非常容易扩展,而调用者 Invoker 和高层次的模块 Client 不产生严重代码耦合。
  3. 与其他模式结合。
    • 结合责任链模式。实现命令族解析任务。
    • 结合模板方法模式。减少 Command 子类膨胀问题。

缺点

  1. 如果有N个命令,Command 子类就是N个,类膨胀较大。

注意事项

  1. 命令模式的 Receiver 在实际应用中一般都会被封装掉(除非非常必要,如撤销处理)。原因是在项目中:约定的优先级最高,每一个命令是对一个或多个 Receiver 的封装,可通过有意义的类名或命令名处理 Command 和 Receiver 的耦合关系(约定),减少高层模块 Client 对低层模块的 Receiver 的依赖关系,提升系统整体稳定性。

扩展

  1. 协调多个对象。Command 可封装多个 Reciever 对象,共同完成一项命令。
  2. 反悔问题。有两种方式解决:
    • 结合备忘录模式还原最后状态,该方法适合接收者为状态的变更情况,不适合事件处理。
    • 增加新命令,实现事件回滚。例如增加撤销命令。

代码演示

以处理文档、图片为例

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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
// 定义 receiver
abstract class Operator {
abstract void add();
abstract void update();
abstract void delete();
public void rollback() { System.out.println("默认回滚操作,需要时覆盖"); }
}

class TextOperator extends Operator {
@Override
void add() { System.out.println("添加文字"); }
@Override
void update() { System.out.println("更新文字"); }
@Override
void delete() { System.out.println("删除文字"); }
@Override
public void rollback() { System.out.println("撤销文字编辑操作"); }
}

class PictureOperator extends Operator {
@Override
void add() { System.out.println("添加图片"); }
@Override
void update() { System.out.println("修改图片"); }
@Override
void delete() { System.out.println("删除图片"); }
}

// 定义命令
abstract class Command {
protected TextOperator text = new TextOperator();
protected PictureOperator picture = new PictureOperator();
// 只有一个方法那就是执行,至于怎么执行交给命令实现类
abstract void execute();
}

class CreateFileCommand extends Command{
@Override
void execute() {
super.text.add();
super.picture.add();
}
}

class DeleteFileCommand extends Command {
@Override
void execute() {
super.text.delete();
super.picture.delete();
}
}

class CancelCreateFileCommand extends Command {
@Override
void execute() {
super.text.rollback();
super.picture.rollback();
}
}

// 需要一个负责人来接收客户发送的命令
class Invoker {
private Command command;
public void setCommand(Command command) { this.command = command; }
public void action() { this.command.execute(); }
}

// 高层模块
class Client {
public static void main(String[] args) {
Invoker invoker = new Invoker();
System.out.println("------客户发来新建图文的命令------");
invoker.setCommand(new CreateFileCommand());
invoker.action();
System.out.println("------客户说需要撤销刚才的创建命令------");
invoker.setCommand(new CancelCreateFileCommand());
invoker.action();
}
}

责任链模式 Chain Of Responsibility

将处理对象串成一条链,请求沿着链传递,直到有对象处理返回结果为止。

类图

使用场景

  1. 需要依次遍历处理对象的情况,请求不关心处理对象都有哪些。
  2. 作为补救模式。例如刚开始的项目需求是一个请求一个处理者,但是随着业务的发展,处理者数量和类型有所增加,这时就可以在第一个处理者后面建立一个链来处理请求。

优点

  1. 将请求和处理分开,解耦。请求者无需知道请求交给谁去处理,处理者也不用知道请求的全貌。

缺点

  1. 可能产生性能问题。链比较长,大量请求从链头遍历到链尾产生性能问题。
  2. 调试不便。长链类似递归的方式对调试产生影响。

注意事项

  1. 链中节点数量要控制,避免出现超长链。一般做法是在 handler 中设置一个最大节点数量,在 setNext 中判断是否已经超过阈值,超过则不允许该链建立,避免无意识地破坏系统性能。

代码演示

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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// 级别
enum Level {
EMERGENCY, SPECIAL, NORMAL, MISS;
public static List<Level> getLevelList() { return Arrays.asList(Level.values()); }
}

// 请求类
class Request {
private Level level;
public Request(Level level) { this.level = level; }
public Level getLevel() { return level; }
}

// 结果类
class Response {}

// handler
abstract class AbstractHandler {
// 下一个处理者
private AbstractHandler next;
public void setNext(AbstractHandler next) { this.next = next; }
// 某个处理者拥有一个级别
protected abstract Level getHandlerLevel();
// 处理方法
protected abstract Response exec(Request request);

// 总的处理逻辑
public final Response handleMessage(Request request) {
Response response = null;
if (isExec(request.getLevel())) {
System.out.println(this.getClass().getSimpleName() + "处理请求!");
response = this.exec(request);
} else {
if (this.next != null) {
System.out.println("交给下个 handler 处理:" +
this.next.getClass().getSimpleName());
response = this.next.handleMessage(request);
} else {
System.out.println("没有 handler 处理该请求:" + request.getLevel());
}
}
return response;
}

// 增加一个是否执行的判断,只有当请求的级别高于 handler 的处理级别时再执行
public final boolean isExec(Level level) {
if (level == null) { return false; }
List<Level> levels = Level.getLevelList();
return levels.indexOf(level) <= levels.indexOf(getHandlerLevel());
}
}

class ConcreteHandler1 extends AbstractHandler {
@Override
protected Level getHandlerLevel() { return Level.EMERGENCY; }
@Override
protected Response exec(Request request) { return new Response(); }
}

class ConcreteHandler2 extends AbstractHandler {
@Override
protected Level getHandlerLevel() { return Level.NORMAL; }
@Override
protected Response exec(Request request) { return new Response(); }
}

class ConcreteHandler3 extends AbstractHandler {
@Override
protected Level getHandlerLevel() { return Level.SPECIAL; }
@Override
protected Response exec(Request request) { return new Response(); }
}

// 通常需要定一个处理器,来组装各个 handler,并指定一个入口
class Processor {
private final static AbstractHandler HANDLER1 = new ConcreteHandler1();
private final static AbstractHandler HANDLER2 = new ConcreteHandler2();
private final static AbstractHandler HANDLER3 = new ConcreteHandler3();
static {
HANDLER1.setNext(HANDLER2);
HANDLER2.setNext(HANDLER3);
}
public Response process(Request request) {
return HANDLER1.handleMessage(request);
}
}

class Client {
public static void main(String[] args) {
Processor processor = new Processor();
System.out.println("-------紧急请求-------");
processor.process(new Request(Level.EMERGENCY));
System.out.println("-------普通请求-------");
processor.process(new Request(Level.NORMAL));
System.out.println("-------忽视请求-------");
processor.process(new Request(Level.MISS));
}
}

策略模式 Strategy

也叫政策模式 Policy Pattern。使用面向对象的继承和多态机制,实现相同接口的算法使之可以互相转化,包含三个角色:

  1. Context 封装角色:也叫上下文角色,起承上启下的作用,屏蔽高层模块对策略、算法的直接访问,封装可能存在的变化。
  2. Strategy 抽象策略角色:策略、算法家族的抽象,通常为接口,定义每个策略或算法必须具有的方法和属性。
  3. ConcreteStrategy 具体策略角色:实现抽象策略中的操作,该类含有具有的算法。

类图

使用场景

  1. 多个类只有在算法或行为上稍有不同的场景。
  2. 算法需要自由切换的场景。例如,算法由使用者决定或者始终在进化。
  3. 需要屏蔽算法规则的场景。对于大量的算法,传递算法的名称或者数字进来,反馈一个运算结果。

优点

  1. 算法可以自由切换。只要实现抽象策略,就称为策略家族的一个成员,通过封装角色对其进行封装,保证对外提供 “可自由切换” 的策略。
  2. 避免使用多重条件判断。如果一个策略家族有5个策略算法,使用多重条件语句不易维护,出错概率增大。
  3. 扩展性良好。增加策略只需要实现接口,其他都不用修改,类似一个可反复拆卸的插件,符合 OCP 原则。

缺点

  1. 策略类数量增多。每个策略都是一个类,复用的可能性很小,类数量增多。
  2. 所有的策略类都需要对外暴露。上层模块必须知道有哪些策略,才能决定使用哪一个策略,这与迪米特法则相违背。但是可以使用其他模式来修正这个缺陷,如工厂方法模式、代理模式或享元模式。

注意事项

  1. 系统中一个策略家族的具体策略数量超过4个,则需要考虑使用混合模式,解决策略类膨胀和对外暴露的问题。

扩展

  1. 策略枚举

代码演示

  1. 普通策略模式

    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
    interface Calculator {
    public int exec(int a, int b);
    }

    class Add implements Calculator {
    @Override
    public int exec(int a, int b) { return a + b; }
    }

    class Sub implements Calculator {
    @Override
    public int exec(int a, int b) { return a - b; }
    }

    class Context {
    private Calculator cal = null;
    public Context(Calculator cal) { this.cal = cal; }
    public int exec(int a, int b, String symbol) { return this.cal.exec(a, b); }
    }

    class Client {
    private static final String ADD_SYMBOL = "+";
    private static final String SUB_SYMBOL = "-";

    public static void main(String[] args) {
    // 输入的两个参数是数字
    int a = 444;
    String symbol = "+";
    int b = 555;

    Context context = null;
    if (symbol.equals(ADD_SYMBOL)) {
    context = new Context(new Add());
    } else if (symbol.equals(SUB_SYMBOL)) {
    context = new Context(new Sub());
    }
    System.out.println("运行结果为:" + a + symbol + b + "=" + context.exec(a, b, symbol));
    }
    }
  2. 策略枚举

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    enum CalculatorEnum {
    ADD("+") {
    @Override
    public int exec(int a, int b) { return a + b; }
    },
    SUB("-") {
    @Override
    public int exec(int a, int b) { return a - b; }
    };
    private String symbol;
    CalculatorEnum(String symbol) { this.symbol = symbol; }
    public abstract int exec(int a, int b);
    }

    class Client2 {
    public static void main(String[] args) {
    int a = 444;
    String symbol = "+";
    int b = 555;
    System.out.println("运行结果为:" + a + symbol + b + "=" +
    CalculatorEnum.ADD.exec(a, b));
    }
    }

迭代器模式 Iterator

能容纳对象的所有类型都可称为容器,如 Collection 集合类型、Set 类型等,迭代器模式就是为解决遍历这些容器中的元素而诞生的。迭代器类似于数据库中的游标,可以在一个容器内上下翻滚,遍历需要查看的元素。包含以下角色:

  1. Iterator 抽象迭代器:负责定义访问和遍历元素的接口,基本上有3个固定方法,first()、next()、hasNext() 是否已经访问到底部。
  2. ConcreteIterator 具体迭代器:实现 迭代器接口,完成容器元素的遍历。
  3. Aggregate 抽象容器:提供创建具体迭代器角色的接口,必然提供一个类似 createIterator() 这样的方法,如 java 中的 iterator() 方法。
  4. Concrete Aggregate 具体容器:实现容器接口定义的方法,创建出容纳迭代器的对象。

类图

优点

  1. 迭代器模式提供了遍历容器的方便性,容器只要管理增减元素即可,需要遍历时交由迭代器进行。

注意事项

  1. 迭代器使用广发,JDK 1.2 版本开始增加 java.util.Iterator 这个接口,并逐步应用到各个聚集类 Collection 中,迭代器模式现已融入到基本 API 中。
  2. Java 中尽量不要自己写迭代器模式,使用 Iterator 一般能够满足要求。
  3. 实际开发中,迭代器的删除方法应该完成2个逻辑,一是删除当前元素,二是当前游标指向下一个元素。

代码演示

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
public class IteratorPattern implements Iterator {
private Vector vector;
public int cursor = 0;

public IteratorPattern(Vector vector) { this.vector = vector; }

@Override
public boolean hasNext() { return this.cursor != this.vector.size(); }
@Override
public Object next() {
Object result = null;
if (this.hasNext()) {
result = this.vector.get(cursor++);
}
return result;
}
@Override
public void remove() {
// 实际开发中,迭代器的删除方法应该完成2个逻辑,一是删除当前元素,二是当前游标指向下一个元素。
this.vector.remove(this.cursor);
}
}

interface Aggregate {
void add(Object o);
void remove(Object o);
Iterator iterator();
}

class ConcreteAggregate implements Aggregate {
private Vector vector = new Vector();
@Override
public void add(Object o) { this.vector.add(o); }
@Override
public void remove(Object o) { this.vector.remove(o); }
@Override
public Iterator iterator() { return new IteratorPattern(this.vector); }
}

class Client {
public static void main(String[] args) {
Aggregate agg = new ConcreteAggregate();
agg.add("aaa");
agg.add("cccc");
agg.add(234324);
Iterator iter = agg.iterator();
while (iter.hasNext()) {
System.out.println(iter.next());
}
}
}

 Comments