行为型模式——模板方法模式(Template Pattern)

文章目录

  • 模板模式(Template Pattern)
      • 应用
        • 使用模板(Java)
        • 应用实例
      • 简介
        • 介绍
        • 意图:
        • UML图
          • 角色
        • 主要解决:
        • 何时使用:
        • 如何解决:
        • 关键代码:
        • 优点:
        • 缺点:
        • 使用场景:
        • 注意事项:
      • JDK使用分析
          • 类Map中的使用

模板模式(Template Pattern)

应用

使用模板(Java)
public class TemplateMethodPattern {
    public static void main(String[] args) {
        AbstractTemplate a = new ConcreteTemplateA();
        a.templateOperation();
        System.out.println("-------------------------------------");
        AbstractClass b = new ConcreteTemplateB();
        b.templateOperation();
    }
}
//抽象类
abstract class AbstractTemplate {
    // 统一的操作,不可变
    public final void templateOperation() {
        //TODO 统一的操作
        System.out.print("1.hookOperation()——");
        hookOperation();
        System.out.println();
        System.out.print("2.abstractMethod()——");
        abstractMethod();
        System.out.println();
        System.out.print("3.calculateAmount()——");
        calculateAmount();
        System.out.println();
    }
    //抽象方法(子类必须实现)
    protected abstract void abstractMethod();
    // 钩子方法(空实现或者默认值)
    protected void hookOperation() { }
    //具体方法,子类无法知晓
    private void calculateAmount() { System.out.print("抽象类中具体方法的实现内容"); }
}
//具体的子类
class ConcreteTemplateA extends AbstractTemplate {
    //重写抽象方法
    @Override
    protected void abstractMethod() { System.out.print("具体操作,子类A_执行"); }
}
class ConcreteTemplateB extends AbstractTemplate {
    //重写抽象方法
    @Override
    protected void abstractMethod() {
        // 具体模板2 业务逻辑
        System.out.print("具体操作,子类B_执行");
    }
    //重写钩子方法
    @Override
    protected void hookOperation() {
        System.out.print("重写了钩子方法,子类B_执行");
    }
}
应用实例
  • Map
  • HashMap

简介

准备一个抽象类,将部分逻辑以具体方法以及具体构造函数的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。这就是模板方法模式的用意。

——《JAVA与模式》

介绍

模板模式(Template Pattern),又叫模板方法模式(Template Method Pattern)行为型模式。

在模板模式中,基本算法固定,算法中部分代码抽象到方法并公开到子类。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。

意图:
  • 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。
  • 模板方法使得子类通过改变一个算法中的指定的一部分代码,从而获得到符合条件的算法。
UML图

行为型模式——模板方法模式(Template Pattern)_第1张图片

角色

抽象类(AbstractTemplate):在抽象类中定义了一系列基本操作,这些基本操作有些是具体的,有些也可以是抽象的。其中有一个具体的方法作为模板方法,该方法定义了一个算法的框架,该方法中根据具体情况进行其中抽象方法进行调用。而该抽象方法将延迟到具体子类中进行实现。

  • 模板抽象类方法类型
    • 模板方法:定义统一模板算法的方法,子类一般不需要重写。一般加上final防止子类篡改。
    • 抽象方法:在抽象类声明、调用,但由其具体子类实现。
    • 具体方法:在抽象类中声明并实现,根据情况来确定是否为子类可知。
    • 钩子方法:在抽象类中声明并实现(可以是空的实现),子类视情况进行重写覆盖,一般是逻辑判断方法。钩子方法的名字应当以do开始,例如doGet()。

**具体子类(ConcreteTemplate):**它是抽象类的子类,用于实现在父类中声明的抽象方法以完成子类特定算法的步骤,也可以覆盖在父类中已经实现的具体基本操作。

主要解决:
  • 大部分算法通用,却因为部分细节不一致,而需要每次都重写该方法。而导致了大量代码重复问题。
何时使用:
  • 有一些通用的方法
如何解决:
  • 将通用算法抽象出来。
关键代码:
  • 通用代码在抽象类实现,变动的细节逻辑在子类实现。
优点:
  1. 封装不变部分,扩展可变部分。
  2. 提取公共代码,便于维护。
  3. 行为由父类控制,子类实现。
缺点:
  • 每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。
使用场景:
  1. 有多个子类共有的方法,且逻辑相同。
  2. 重要的、复杂的方法,可以考虑作为模板方法。
注意事项:

为防止恶意操作,一般模板方法都加上 final 关键词。

JDK使用分析

类Map中的使用
public interface Map<K,V> {
    ...
    V remove(Object key);
    ...
    default boolean remove(Object key, Object value) {
        Object curValue = get(key);
        if (!Objects.equals(curValue, value) ||
            (curValue == null && !containsKey(key))) {
            return false;
        }
        remove(key);
        return true;
    }
}

在上述代码接口中:

  • Map.remove(Object key)等作为抽象方法,在子类中进行实现。
  • Map.remove(Object key, Object value)作为模板方法,是调用抽象方法的固定算法。
public abstract class AbstractMap<K,V> implements Map<K,V> {
    public V remove(Object key) {
        Iterator<Entry<K,V>> i = entrySet().iterator();
        Entry<K,V> correctEntry = null;
        if (key==null) {
            while (correctEntry==null && i.hasNext()) {
                Entry<K,V> e = i.next();
                if (e.getKey()==null)
                    correctEntry = e;
            }
        } else {
            while (correctEntry==null && i.hasNext()) {
                Entry<K,V> e = i.next();
                if (key.equals(e.getKey()))
                    correctEntry = e;
            }
        }

        V oldValue = null;
        if (correctEntry !=null) {
            oldValue = correctEntry.getValue();
            i.remove();
        }
        return oldValue;
    }
}

而在Hashmap的父类AbstractMap便实现了上述的抽象方法,从而组合为符合该类需要的remove算法。

      oldValue = correctEntry.getValue();
        i.remove();
    }
    return oldValue;
}

}


而在`Hashmap`的父类`AbstractMap`便实现了上述的抽象方法,从而组合为符合该类需要的remove算法。

你可能感兴趣的:(设计模式,模板方法模式,java,开发语言,设计模式,uml)