Java 中的绞杀者模式:使用增量更新现代化遗留系统
也称为
- 绞杀者无花果
绞杀者设计模式的意图
绞杀者模式通过在旧系统旁边构建一个新系统来逐步替换遗留系统,最终“绞杀”掉旧系统。使用该模式可以实现从旧系统到新系统的无缝过渡。
绞杀者模式的详细说明,附带现实世界例子
现实世界的例子
想象一下,一个城市规划部门决定对每天通勤必不可少的一座老桥进行现代化改造。他们没有拆除老桥,造成重大交通中断,而是选择在旁边建造一座新的现代桥梁。随着新桥各个部分完工,交通流量逐渐从老桥转移到新桥。最终,所有交通流量都转移到新桥,老桥则被退役或拆除。这样一来,过渡过程非常平稳,城市日常活动几乎不受影响。这种方法与绞杀者设计模式非常相似,它逐步用新系统替换遗留系统,确保在过渡过程中系统持续运行。
通俗地说
绞杀者设计模式通过在遗留系统旁边开发一个新系统,并逐步迁移功能,最终完全替换遗留系统,从而逐步替换遗留系统。
维基百科说
绞杀者设计模式通过逐步用新系统替换旧系统来实现遗留系统的逐步迁移。它用新代码包装旧代码,重定向或记录旧代码的使用,以确保平稳过渡。这种模式以绞杀者无花果植物命名,这种植物围绕着寄主树生长,最终完全取代寄主树。它对于现代化单体应用程序并将其迁移到微服务架构特别有用,可以将风险和中断降到最低。
Java 中绞杀者模式的编程示例
Java 中的绞杀者设计模式是一种软件设计模式,它通过逐步用新的应用程序和服务替换遗留系统的特定功能部分来实现遗留系统的逐步迁移。随着遗留系统中的功能被替换,新系统最终会替换掉所有旧系统功能,从而“绞杀”掉旧系统,并允许你将其停用。
在提供的代码中,我们有一个绞杀者模式实际应用的示例。OldArithmetic
类代表遗留系统,而 HalfArithmetic
和 NewArithmetic
类代表处于不同开发阶段的新系统。
让我们分解代码,了解绞杀者模式是如何实现的。
public class OldArithmetic {
private final OldSource source;
public OldArithmetic(OldSource source) {
this.source = source;
}
// The sum and mul methods represent the functionality of the legacy system.
public int sum(int... nums) {
return source.accumulateSum(nums);
}
public int mul(int... nums) {
return source.accumulateMul(nums);
}
}
OldArithmetic
类代表遗留系统。它有两个方法,sum
和 mul
,它们依赖于 OldSource
类。
public class HalfArithmetic {
private final HalfSource newSource;
private final OldSource oldSource;
public HalfArithmetic(HalfSource newSource, OldSource oldSource) {
this.newSource = newSource;
this.oldSource = oldSource;
}
// The sum method has been migrated to use the new source.
public int sum(int... nums) {
return newSource.accumulateSum(nums);
}
// The mul method still uses the old source.
public int mul(int... nums) {
return oldSource.accumulateMul(nums);
}
// The ifHasZero method is a new feature added in the new system.
public boolean ifHasZero(int... nums) {
return !newSource.ifNonZero(nums);
}
}
HalfArithmetic
类代表迁移过程中的系统。它依赖于 OldSource
和 HalfSource
类。sum
方法已迁移为使用新的源,而 mul
方法仍然使用旧的源。ifHasZero
方法是新系统中添加的新功能。
public class NewArithmetic {
private final NewSource source;
public NewArithmetic(NewSource source) {
this.source = source;
}
// All methods now use the new source.
public int sum(int... nums) {
return source.accumulateSum(nums);
}
public int mul(int... nums) {
return source.accumulateMul(nums);
}
public boolean ifHasZero(int... nums) {
return !source.ifNonZero(nums);
}
}
NewArithmetic
类代表迁移过程后的系统。它只依赖于 NewSource
类。所有方法现在都使用新的源。
以下是执行我们示例的 main
方法。
public static void main(final String[] args) {
final var nums = new int[]{1, 2, 3, 4, 5};
//Before migration
final var oldSystem = new OldArithmetic(new OldSource());
oldSystem.sum(nums);
oldSystem.mul(nums);
//In process of migration
final var halfSystem = new HalfArithmetic(new HalfSource(), new OldSource());
halfSystem.sum(nums);
halfSystem.mul(nums);
halfSystem.ifHasZero(nums);
//After migration
final var newSystem = new NewArithmetic(new NewSource());
newSystem.sum(nums);
newSystem.mul(nums);
newSystem.ifHasZero(nums);
}
控制台输出
13:02:25.030 [main] INFO com.iluwatar.strangler.OldArithmetic -- Arithmetic sum 1.0
13:02:25.032 [main] INFO com.iluwatar.strangler.OldSource -- Source module 1.0
13:02:25.032 [main] INFO com.iluwatar.strangler.OldArithmetic -- Arithmetic mul 1.0
13:02:25.032 [main] INFO com.iluwatar.strangler.OldSource -- Source module 1.0
13:02:25.032 [main] INFO com.iluwatar.strangler.HalfArithmetic -- Arithmetic sum 1.5
13:02:25.032 [main] INFO com.iluwatar.strangler.HalfSource -- Source module 1.5
13:02:25.033 [main] INFO com.iluwatar.strangler.HalfArithmetic -- Arithmetic mul 1.5
13:02:25.033 [main] INFO com.iluwatar.strangler.OldSource -- Source module 1.0
13:02:25.033 [main] INFO com.iluwatar.strangler.HalfArithmetic -- Arithmetic check zero 1.5
13:02:25.033 [main] INFO com.iluwatar.strangler.HalfSource -- Source module 1.5
13:02:25.034 [main] INFO com.iluwatar.strangler.NewArithmetic -- Arithmetic sum 2.0
13:02:25.034 [main] INFO com.iluwatar.strangler.NewSource -- Source module 2.0
13:02:25.034 [main] INFO com.iluwatar.strangler.NewArithmetic -- Arithmetic mul 2.0
13:02:25.034 [main] INFO com.iluwatar.strangler.NewSource -- Source module 2.0
13:02:25.034 [main] INFO com.iluwatar.strangler.NewArithmetic -- Arithmetic check zero 2.0
13:02:25.035 [main] INFO com.iluwatar.strangler.NewSource -- Source module 2.0
这是绞杀者模式的一个典型示例。遗留系统 (OldArithmetic
) 逐步被新系统 (HalfArithmetic
和 NewArithmetic
) 替换。新系统是增量开发的,在每个阶段,它都会“绞杀”掉遗留系统的一部分,直到遗留系统完全被替换。
何时在 Java 中使用绞杀者模式
- 当你需要逐步替换单体或遗留系统时使用。
- 非常适合由于风险或复杂性而无法一次性替换系统的场景。
- 当你需要现代化应用程序的一部分,同时确保系统持续运行时,可以使用它。
- 非常适合需要零停机更新的应用程序,绞杀者模式支持复杂 Java 系统中的增量更新。
绞杀者模式 Java 教程
Java 中绞杀者模式的现实世界应用
- 用微服务架构替换遗留单体应用程序。
- 从内部部署系统迁移到云端系统。
- 逐步从旧数据库模式迁移到新数据库模式,同时避免停机。
绞杀者模式的优缺点
优势
- 通过允许逐步替换来降低风险。
- 在迁移过程中实现持续交付和运营。
- 允许在完全替换之前测试和验证新组件。
权衡
- 需要管理新旧系统之间的交互,这可能很复杂。
- 由于旧系统和新系统的共存,可能会引入暂时性的性能开销。
- 由于需要集成,可能会增加初始开发时间。