模板模式:一种体现多态的设计模式
共 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乐园