模板模式:一种体现多态的设计模式

JAVA乐园

共 3441字,需浏览 7分钟

 ·

2020-12-08 21:26

点击上方「蓝字」关注我们

0x01:模板模式

模板模式(Template),又叫模板方法模式(Template Method),在一个抽象类公开定义了执行它的方法的模板。它的子类可以按需重写方法实现,但调用将以抽象类中定义的方式进行。模板方法模式:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构,就可以重定义该算法的某些特定步骤。UML类图如下:

 主要包含如下角色:

  • AbstractClass(抽象模板类):在抽象类中定义了一系列基本操作,这些基本操作可以是具体的,也可以是抽象的,每一个基本操作对应算法的一个步骤,在其子类中可以重定义或实现这些步骤。同时,在抽象类中实现了一个模板方法(Template Method),用于定义一个算法的框架,模板方法不仅可以调用在抽象类中实现的基本方法,也可以调用在抽象类的子类中实现的基本方法,还可以调用其他对象中的方法。

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


抽象模板类:定义一个模板方法来组合sing()和dance()两个方法形成一个算法,然后让子类重定义这两个方法。

public abstract class AbstractClass {

    public abstract void sing(String name);

    public abstract void dance(String name);

    public void templateMethd(String name{
        sing(name);
        dance(name);
    }

}

具体模板类:这里定义两个具体模板类,ConcreteClassLiMing及ConcreteClassLiuDeHua来进行测试,继承抽象模板类,实现具体方法。

public class ConcreteClassLiMing extends AbstractClass {

    @Override
    public void sing(String name) {
        System.out.println(name + "在唱歌");
    }

    @Override
    public void dance(String name) {
        System.out.println(name + "在跳舞");
    }

}

public class ConcreteClassLiuDeHua extends AbstractClass {

    @Override
    public void sing(String name) {
        System.out.println(name + "在唱歌");
    }

    @Override
    public void dance(String name) {
        System.out.println(name + "在跳舞");
    }

}

Client客户端:

public class Client {

    public static void main(String[] args{
        AbstractClass abstractClass = null;

        abstractClass = new ConcreteClassLiMing();
        abstractClass.templateMethd("黎明");

        abstractClass = new ConcreteClassLiuDeHua();
        abstractClass.templateMethd("刘德华");
    }

}

通过以上代码就实现了一个简单的模板模式,模板模式的优点:封装不变部分,扩展可变部分。提取公共代码,便于维护。行为由父类控制,子类实现;缺点:每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。


0x02:JDK中的模板模式

如果有了解过java.util.concurrent.locks包的AbstractQueuedSynchronizer类(简称AQS),就会发现AbstractQueuedSynchronizer类(同步器)是一个非常经典的模板模式。如果需要自定义同步器,一般方法是:继承AQS,并重写指定方法(无非是按照自己定义的规则对state的获取与释放);将AQS组合在自定义同步组件的实现中,并调用模板方法,而这些模板方法会调用重写的方法。

//该线程是否正在独占资源。只有用到condition才需要去实现它。
isHeldExclusively();
//独占方式。尝试获取资源,成功则返回true,失败则返回false。
tryAcquire(int);
//独占方式。尝试释放资源,成功则返回true,失败则返回false。
tryRelease(int);
////共享方式。尝试获取资源。负数表示失败;0表示成功,但没有剩余可用资源;正数表示成功,且有剩余资源。
tryAcquireShared(int);
////共享方式。尝试释放资源,成功则返回true,失败则返回false。
tryReleaseShared(int);

默认情况下,以上这些方法都抛出 UnsupportedOperationException。这些方法的实现必须是内部线程安全的,并且通常应该简短而不是阻塞。AQS类中的其他方法都是final ,所以无法被其他类使用,只有这几个方法可以被其他类使用。


0x03:Spring中的模板模式

Spring作为一个特优秀的框架,底层大量使用模板模式。以Spring的事务管理器来讲下Spring中的模板模式。

AbstractPlatformTransactionManager是Spring中的模板抽象类,它的继承关系图如下:

实现了PlatformTransactionManager接口,重载了接口中的方法。

  • 模板方法:事务管理器中抽象类中的模板方法不止一个,比如以下两个方法

//提交事务
public final void commit()

//获取TransactionStatus
public final TransactionStatus getTransaction()

这两个方法都对于自己要实现的逻辑搭建了一个骨架,主要的功能是由抽象方法完成,由子类来完成。

  • 抽象方法事务管理器抽象类中的抽象方法定义了多个,分别用于处理不同的业务逻辑,由子类实现其中具体的逻辑。

//提交事务
protected abstract void doCommit(DefaultTransactionStatus status);

//回滚事务
protected abstract void doRollback(DefaultTransactionStatus status);

//开始事务
protected abstract void doBegin(Object transaction, TransactionDefinition definition)

//获取当前的事务对象
protected abstract Object doGetTransaction()

抽象方法的定义便于子类去扩展,在保证算法逻辑不变的情况下,子类能够定制自己的实现。

  • 具体子类:其中有DataSourceTransactionManager、JtaTransactionManager、RabbitTransactionManager等,类继承关系如下:

另外还有JdbcTemplate、JpaTemplate等使用了模板模式。其他需要大家慢慢去发现,去学习~~~

书山有路勤为径,学海无涯苦作舟!

扫码二维码

获取更多精彩

Java乐园

有用!分享+在看☟
浏览 5
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报