我们首先来看模板模式(Template):
定义:
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
核心思想:
父类定义骨架,子类实现某些细节。
使用场景:
1、有多个子类共有的方法,且逻辑相同。
2、重要的、复杂的方法,可以考虑作为模板方法。
注意事项:
为了防止子类重写父类的骨架方法,可以在父类中对骨架方法使用final。对于需要子类实现的抽象方法,一般声明为protected,使得这些方法对外部客户端不可见。
举例实现:
父类(定义骨架):
public abstract class DodishTemplate {
//具体的整个固定流程,使用final防止子类改写
public final void dodish(){
this.preparation();
this.doing();
this.carriedDishes();
}
//具体操作交由子类实现
//备料
public abstract void preparation();
//做菜
public abstract void doing();
//上菜
public abstract void carriedDishes ();
}
子类(具体实现):
//西红柿炒鸡蛋
public class EggsWithTomato extends DodishTemplate{
@Override
public void preparation() {
System.out.println("洗并切西红柿,打鸡蛋。");
}
@Override
public void doing() {
System.out.println("鸡蛋倒入锅里,然后倒入西红柿一起炒。");
}
@Override
public void carriedDishes() {
System.out.println("将炒好的西红寺鸡蛋装入碟子里,端给客人吃。");
}
//红烧肉
public class Bouilli extends DodishTemplate{
@Override
public void preparation() {
System.out.println("切猪肉和土豆。");
}
@Override
public void doing() {
System.out.println("将切好的猪肉倒入锅中炒一会然后倒入土豆连炒带炖。");
}
@Override
public void carriedDishes() {
System.out.println("将做好的红烧肉盛进碗里端给客人吃。");
}
}
最终测试:
public class Main {
public static void main(String[] args) {
DodishTemplate eggsWithTomato = new EggsWithTomato();
eggsWithTomato.dodish();
System.out.println("-----------------------------");
DodishTemplate bouilli = new Bouilli();
bouilli.dodish();
}
}
总结:
模板方法是一种高层定义骨架,底层实现细节的设计模式,适用于流程固定,但某些步骤不确定或可替换的情况。相对于其他设计模式而言,模板方法只有一棵继承树,并没有使用委派。
———————————————————————————————————————————
接下来我们来看迭代器模式(Iterator):
定义:
提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。
核心思想:
把在元素之间游走的责任交给迭代器,而不是聚合对象。
使用场景:
1、访问一个聚合对象的内容而无须暴露它的内部表示。
2、需要为聚合对象提供多种遍历方式。
3、为遍历不同的聚合结构提供一个统一的接口.
图示:
Iterator(抽象迭代器): 它定义了访问和遍历元素的接口,声明了用于遍历数据元素的方法,例如:、用于访问下一个元素的next()方法,用于判断是否还有下一个元素的hasNext()方法等,在具体迭代器中将实现这些方法。
ConcreteIterator(具体迭代器): 它实现了抽象迭代器接口,完成对聚合对象的遍历,同时在具体迭代器中通过游标来记录在聚合对象中所处的当前位置,在具体实现时,游标通常是一个表示位置的非负整数。
Aggregate(抽象聚合类): 它用于存储和管理元素对象,声明一个createIterator()方法用于创建一个迭代器对象,充当抽象迭代器工厂角色。
ConcreteAggregate(具体聚合类): 它实现了在抽象聚合类中声明的createIterator()方法,该方法返回一个与该具体聚合类对应的具体迭代器ConcreteIterator实例。
举例实现:
//Iterable<T>为Aggregate(抽象聚合类);
//ConcreteAggregate(具体聚合类):
public class ReverseArrayCollection<T> implements Iterable<T> {
// 以数组形式持有集合:
private T[] array;
public ReverseArrayCollection(T... objs) {
this.array = Arrays.copyOfRange(objs, 0, objs.length);
}
public Iterator<T> iterator() {
return new ReverseIterator();
}
}
//Iterator<T>为Iterator(抽象迭代器);
//ConcreteIterator(具体迭代器):
private class ReverseIterator implements Iterator<T> {
// 索引位置:
int index;
public ReverseIterator() {
// 创建Iterator时,索引在数组末尾:
this.index = ReverseArrayCollection.this.array.length;
}
public boolean hasNext() {
// 如果索引大于0,那么可以移动到下一个元素(倒序往前移动):
return index > 0;
}
public T next() {
// 将索引移动到下一个元素并返回(倒序往前移动):
index--;
return array[index];
}
}
}
迭代器的使用(list为例):
Iterator iterator = list.iterator();
while(iterator.hasNext()){
String string = iterator.next();
//do something
}
总结:
Iterator模式常用于遍历集合,它允许集合提供一个统一的Iterator接口来遍历元素,同时保证调用者对集合内部的数据结构一无所知,从而使得调用者总是以相同的接口遍历各种不同类型的集合。因为Java已经为我们准备了Iterator接口与Iterable接口,所以我们只需要实现具体类就可以了。