如何为StringBuilder和StringBuffer提取重复代码至公共方法?
解决StringBuffer与StringBuilder重复代码提取问题
嘿,我完全懂你遇到的困扰——StringBuffer和StringBuilder功能几乎一致,但偏偏是两个独立的类,既没有共同的、包含核心操作的父类(除了Object),也没实现同一个能覆盖所有你需要的方法的接口,所以一开始想靠泛型解决确实走不通。不过咱们有几个实用的办法来提取重复代码:
方法一:用函数式接口封装操作(推荐)
利用两者方法签名完全一致的特点,用Supplier来创建实例,用Consumer来封装重复的逻辑,这样就能把公共逻辑抽离出来:
// 公共方法:负责创建实例并执行重复逻辑 private String processMutableString(Supplier<? extends Appendable> instanceCreator, Consumer<? super Appendable> logic) { Appendable mutableStr = instanceCreator.get(); logic.accept(mutableStr); // 如果需要返回最终字符串,直接转换即可 return mutableStr.toString(); } // 调用StringBuilder版本 public String buildWithStringBuilder() { return processMutableString( StringBuilder::new, sb -> { sb.append("Hello"); sb.append(" World"); // 这里放所有重复的操作,比如插入、删除、反转等 if (sb instanceof StringBuilder) { ((StringBuilder) sb).reverse(); // 若用到Appendable没有的方法,需要强转 } } ); } // 调用StringBuffer版本 public String buildWithStringBuffer() { return processMutableString( StringBuffer::new, sb -> { sb.append("Hello"); sb.append(" World"); // 和上面完全一样的重复逻辑 if (sb instanceof StringBuffer) { ((StringBuffer) sb).reverse(); } } ); }
如果你的重复逻辑用到了Appendable接口没有定义的方法(比如reverse()、delete()),可以在Consumer里做个简单的类型判断强转,或者自定义一个包含这些方法的函数式接口来更优雅地处理。
方法二:工具类静态方法(适合简单逻辑)
如果你的重复逻辑比较简单,可以直接写一个静态工具方法,通过instanceof来处理两种类型:
public static void applyCommonLogic(Object mutableString) { if (mutableString instanceof StringBuilder sb) { sb.append("Common content"); sb.reverse(); } else if (mutableString instanceof StringBuffer sb) { sb.append("Common content"); sb.reverse(); } } // 调用时 StringBuilder sb = new StringBuilder(); applyCommonLogic(sb); StringBuffer sbf = new StringBuffer(); applyCommonLogic(sbf);
这种方式代码量少,但扩展性稍差,如果以后新增类似的可变字符串类,需要修改工具方法。
方法三:适配器模式(适合复杂逻辑)
如果你的重复逻辑非常复杂,可以创建一个适配器接口,然后为StringBuilder和StringBuffer分别写实现类,把公共逻辑放在适配器的默认方法或者抽象类里:
// 定义适配器接口 interface MutableStringAdapter { void append(String content); void reverse(); String getResult(); // 公共逻辑放在默认方法里 default void applyCommonLogic() { append("Common prefix"); reverse(); append("Common suffix"); } } // StringBuilder适配器 class StringBuilderAdapter implements MutableStringAdapter { private final StringBuilder sb = new StringBuilder(); @Override public void append(String content) { sb.append(content); } @Override public void reverse() { sb.reverse(); } @Override public String getResult() { return sb.toString(); } } // StringBuffer适配器 class StringBufferAdapter implements MutableStringAdapter { private final StringBuffer sb = new StringBuffer(); @Override public void append(String content) { sb.append(content); } @Override public void reverse() { sb.reverse(); } @Override public String getResult() { return sb.toString(); } } // 使用示例 MutableStringAdapter sbAdapter = new StringBuilderAdapter(); sbAdapter.applyCommonLogic(); String result1 = sbAdapter.getResult(); MutableStringAdapter sbfAdapter = new StringBufferAdapter(); sbfAdapter.applyCommonLogic(); String result2 = sbfAdapter.getResult();
这种方式最优雅,但适合逻辑复杂、需要频繁复用的场景,小逻辑的话有点过度设计。
总结一下:泛型确实帮不上忙,因为这两个类没有共同的操作契约,所以得靠函数式编程、类型判断或者适配器来解决重复代码问题,根据你的逻辑复杂度选对应的方式就好~
内容的提问来源于stack exchange,提问作者zond
相关产品推荐
相关产品推荐

