【设计模式】JAVA Design Patterns——Curiously Recurring Template Pattern(奇异递归模板模式)

简介: 该文介绍了一种C++的编程技巧——奇异递归模板模式(CRTP),旨在让派生组件能继承基本组件的特定功能。通过示例展示了如何创建一个`Fighter`接口和`MmaFighter`类,其中`MmaFighter`及其子类如`MmaBantamweightFighter`和`MmaHeavyweightFighter`强制类型安全,确保相同重量级的拳手之间才能进行比赛。这种设计避免了不同重量级拳手间的错误匹配,编译时会报错。CRTP适用于处理类型冲突、参数化类方法和限制方法只对相同类型实例生效的情况。

🔍目的
允许派生组件从与派生类型兼容的基本组件继承某些功能。

🔍解释
真实世界例子
对于正在策划赛事的综合格斗推广活动来说,确保在相同重量级的运动员之间组织比赛至关重要。这样可以防止体型明显不同的拳手之间的不匹配,例如重量级拳手与雏量级拳手的对决。

通俗描述
使类型中的某些方法接受特定于其子类型的参数。

维基百科
奇异递归模板模式(curiously recurring template pattern,CRTP)是C++模板编程时的一种惯用法:其中类X派生自使用X本身作为模板参数的类模板实例化。

程序实例
定义一个通用接口Fighter

public interface Fighter {

void fight(T t);

}
定义MmaFighter类用于实例化按重量级别区分的拳手

public class MmaFighter> implements Fighter {

private final String name;
private final String surname;
private final String nickName;
private final String speciality;

public MmaFighter(String name, String surname, String nickName, String speciality) {
this.name = name;
this.surname = surname;
this.nickName = nickName;
this.speciality = speciality;
}

@Override
public void fight(T opponent) {
LOGGER.info("{} is going to fight against {}", this, opponent);
}

@Override
public String toString() {
return name + " \"" + nickName + "\" " + surname;
}

定义MmaFighter 的一些子类型

class MmaBantamweightFighter extends MmaFighter {

public MmaBantamweightFighter(String name, String surname, String nickName, String speciality) {
super(name, surname, nickName, speciality);
}

}

public class MmaHeavyweightFighter extends MmaFighter {

public MmaHeavyweightFighter(String name, String surname, String nickName, String speciality) {
super(name, surname, nickName, speciality);
}

}
效果: 允许拳手与相同重量级的对手交手,如果对手是不同重量级,则会出现错误

MmaBantamweightFighter fighter1 = new MmaBantamweightFighter("Joe", "Johnson", "The Geek", "Muay Thai");
MmaBantamweightFighter fighter2 = new MmaBantamweightFighter("Ed", "Edwards", "The Problem Solver", "Judo");
fighter1.fight(fighter2); // This is fine

MmaHeavyweightFighter fighter3 = new MmaHeavyweightFighter("Dave", "Davidson", "The Bug Smasher", "Kickboxing");
MmaHeavyweightFighter fighter4 = new MmaHeavyweightFighter("Jack", "Jackson", "The Pragmatic", "Brazilian Jiu-Jitsu");
fighter3.fight(fighter4); // This is fine too

fighter1.fight(fighter3); // This will raise a compilation error
🔍类图
image.png

🔍适用场景
在以下情况下使用CRTP

在对象层次结构中链接方法时存在类型冲突
您想使用一个参数化的类方法,该方法可以接受类的子类作为参数,从而可以应用于继承自类的对象
您希望某些方法仅适用于相同类型的实例,例如实现相互比较。

相关文章
|
设计模式 Java 数据安全/隐私保护
Java 设计模式:装饰者模式(Decorator Pattern)
装饰者模式属于结构型设计模式,允许通过动态包装对象的方式为对象添加新功能,提供比继承更灵活的扩展方式。该模式通过组合替代继承,遵循开闭原则(对扩展开放,对修改关闭)。
|
搜索推荐 Java 数据库连接
Java|在 IDEA 里自动生成 MyBatis 模板代码
基于 MyBatis 开发的项目,新增数据库表以后,总是需要编写对应的 Entity、Mapper 和 Service 等等 Class 的代码,这些都是重复的工作,我们可以想一些办法来自动生成这些代码。
588 6
|
算法 Java Linux
java制作海报四:java BufferedImage 转 InputStream 上传至OSS。png 图片合成到模板(另一个图片)上时,透明部分变成了黑色
这篇文章主要介绍了如何将Java中的BufferedImage对象转换为InputStream以上传至OSS,并解决了png图片合成时透明部分变黑的问题。
1071 1
|
小程序
java--微信小程序发送模板消息
java--微信小程序发送模板消息
747 0
|
Java
Java PDF模板生成PDF
Java PDF模板生成PDF
445 1
|
设计模式 Java
设计模式--适配器模式 Adapter Pattern
这篇文章介绍了适配器模式,包括其基本介绍、工作原理以及类适配器模式、对象适配器模式和接口适配器模式三种实现方式。
|
8月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
409 1
|
8月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
384 1
|
9月前
|
数据采集 存储 弹性计算
高并发Java爬虫的瓶颈分析与动态线程优化方案
高并发Java爬虫的瓶颈分析与动态线程优化方案
Java 数据库 Spring
409 0