You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

遗留项目中MyClass字符串修改的设计模式优化方案咨询

问题描述

我正在维护一个遗留项目,简化后的场景如下:

存在一个10000行代码的MyClass类,核心定义如下:

public class MyClass {
    private String myString;
    // 更多成员变量,遗留类共10000行代码

    public String getMyString() {
        return myString;
    }

    public void setMyString(String myString) {
        this.myString = myString;
    }
}

另外有一个跨包的MyStringHelper类,通过静态方法修改MyClass实例的myString:

public class MyStringHelper {
    public static void modifyMyString(MyClass myClass) {
        // 对myClass的myString做一些处理
        myClass.setMyString("BLABLA");
    }

    public static void modifyMyStringII(MyClass myClass) {
        // 对myClass的myString做一些处理
        String old = myClass.getMyString();
        myClass.setMyString(old + "BLABLA");
    }
}

当前实现依赖开发者仅通过MyStringHelper修改myString,不能直接调用MyClass::setMyString,但这种约束完全靠自觉,很容易出错。

想请教:从设计模式角度,有没有优雅的解决方案?另外,封装一个MyString类的方案是否更优?该类示例定义如下:

public class MyString {
    private String myString;

    public MyString(Trans trans) {
        this.myString = myString;
    }

    public String getMyString() {
        return myString;
    }

    public void modifyMyString() {
        ...
    }

    public void modifyMyStringII() {
        ...
    }
}

解决方案

方案1:将修改逻辑内聚到MyClass(优先适配遗留代码)

既然MyStringHelper的逻辑是专门针对MyClass的myString,最直接的做法是把这些行为迁移到MyClass内部,同时逐步限制setMyString的公开访问:

  1. 在MyClass中新增对应修改方法,并标记旧方法为废弃:
public class MyClass {
    private String myString;
    // 其他遗留代码

    public String getMyString() {
        return myString;
    }

    // 标记为废弃,明确提示开发者不要直接调用
    @Deprecated
    public void setMyString(String myString) {
        this.myString = myString;
    }

    // 迁移MyStringHelper的逻辑到这里
    public void modifyMyString() {
        // 原Helper里的处理逻辑
        this.myString = "BLABLA";
    }

    public void modifyMyStringII() {
        // 原Helper里的处理逻辑
        this.myString = this.myString + "BLABLA";
    }
}
  1. 修改MyStringHelper的静态方法,内部调用MyClass的新方法,同样标记为废弃,引导开发者直接使用MyClass的方法:
public class MyStringHelper {
    @Deprecated
    public static void modifyMyString(MyClass myClass) {
        myClass.modifyMyString();
    }

    @Deprecated
    public static void modifyMyStringII(MyClass myClass) {
        myClass.modifyMyStringII();
    }
}

优势:

  • 改动量极小,不用大规模修改遗留代码
  • 符合封装原则,数据和操作数据的行为归为一体
  • 通过@Deprecated平滑过渡,避免硬切换导致的编译错误

方案2:封装MyString值对象(彻底重构)

如果myString的修改逻辑复杂,且后续有扩展需求,封装成值对象是更彻底的优化方案,符合单一职责原则:

  1. 完善MyString类,把所有修改逻辑内聚到自身(修正原示例构造函数的参数问题):
public class MyString {
    private String value;

    public MyString(String initialValue) {
        this.value = initialValue;
    }

    public String getValue() {
        return value;
    }

    public void modifyToBlabla() {
        this.value = "BLABLA";
    }

    public void appendBlabla() {
        this.value += "BLABLA";
    }

    // 可选:设计成不可变对象,更符合值对象规范
    public MyString appendBlablaImmutable() {
        return new MyString(this.value + "BLABLA");
    }
}
  1. 修改MyClass,用MyString替代原有的String成员,移除直接修改字符串的setMyString:
public class MyClass {
    private MyString myString;
    // 其他遗留代码

    public MyString getMyString() {
        return myString;
    }

    // 仅保留初始化或替换整个MyString的方法(如果需要)
    public void setMyString(MyString myString) {
        this.myString = myString;
    }
}
  1. 使用方式变为:
MyClass myObj = new MyClass();
myObj.getMyString().modifyToBlabla();
// 不可变版本的调用方式
myObj.setMyString(myObj.getMyString().appendBlablaImmutable());

优势:

  • 彻底封装myString的所有操作,杜绝直接修改底层字符串的可能
  • 扩展性强,新增修改逻辑只需在MyString中添加方法
  • 不可变设计能避免并发场景下的线程安全问题

注意事项:

  • 对遗留代码侵入性较大,需要修改所有直接调用getMyString()获取字符串的地方(比如改成myObj.getMyString().getValue())
  • 建议分阶段重构,先保留getMyString()返回String的兼容方法,再逐步切换

方案对比

  • 若只是快速解决“开发者直接调用setMyString”的问题,优先选方案1,改动小、风险低
  • 若myString业务逻辑复杂且有长期扩展需求,选方案2,架构更清晰、符合面向对象设计原则

内容的提问来源于stack exchange,提问作者AndreasInfo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 08:31:08