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

C#状态模式中父类变量定义与初始化:子类共享变量如何从主类赋值

嘿,我完全懂你现在的处境——在状态模式里折腾共享变量,想在抽象父类里定义一次让所有子类复用,但主类怎么初始化这些protected变量又拿不准,还要应付数量不固定的子类对吧?别慌,我给你几个实用的解决方案,都是在实际开发中验证过的:

核心原则:封装优先,避免直接暴露protected变量

首先得说,别想着让主类直接去改父类的protected变量——这既不符合封装原则,跨包的话还根本访问不了。更好的思路是让父类自己管理共享变量,主类只需要通过父类提供的“入口”来初始化,子类自动继承复用。

方案1:构造函数注入(适合每个状态实例需要独立共享变量的场景)

如果你的共享变量是每个状态实例初始化时确定的,把它们放到父类的构造函数里,子类创建时调用父类构造传递参数就行。这样不管子类有多少个,都只需要在父类定义一次变量:

// 抽象父类:管理共享变量,定义构造方法
abstract class BaseStep {
    protected String sharedConfig;
    protected int sharedCounter;

    // 父类构造:接收初始化参数,给共享变量赋值
    public BaseStep(String sharedConfig, int sharedCounter) {
        this.sharedConfig = sharedConfig;
        this.sharedCounter = sharedCounter;
    }

    // 子类必须实现的抽象方法
    public abstract void execute();
}

// 子类1:调用父类构造,自动继承共享变量
class Step01 extends BaseStep {
    public Step01(String sharedConfig, int sharedCounter) {
        super(sharedConfig, sharedCounter);
    }

    @Override
    public void execute() {
        System.out.println("Step01执行 | 配置:" + sharedConfig + " | 计数器:" + sharedCounter);
    }
}

// 子类2:同理,不用重复定义变量
class Step02 extends BaseStep {
    public Step02(String sharedConfig, int sharedCounter) {
        super(sharedConfig, sharedCounter);
    }

    @Override
    public void execute() {
        sharedCounter++; // 子类可以修改共享变量
        System.out.println("Step02执行 | 配置:" + sharedConfig + " | 计数器:" + sharedCounter);
    }
}

// 主类:初始化变量,传递给子类构造
public class StateDemo {
    public static void main(String[] args) {
        // 先初始化共享变量
        String globalConfig = "系统全局配置V1.0";
        int initCounter = 0;

        // 创建子类时,把变量传给父类构造
        BaseStep step1 = new Step01(globalConfig, initCounter);
        BaseStep step2 = new Step02(globalConfig, initCounter);

        step1.execute();
        step2.execute();
    }
}

方案2:静态共享变量(适合所有子类实例共用同一组变量的场景)

如果你的共享变量是全局通用的(比如所有状态实例都用同一个配置、同一个计数器),把父类的变量设为static protected,然后在父类加一个静态初始化方法,主类直接调用就行——这样不管子类有多少,都共享同一组变量:

// 抽象父类:静态共享变量+初始化方法
abstract class BaseStep {
    // 静态变量:所有子类实例共用
    protected static String sharedGlobalConfig;
    protected static int sharedGlobalCounter;

    // 静态初始化方法:主类调用这个方法来赋值
    public static void initSharedVars(String config, int counter) {
        sharedGlobalConfig = config;
        sharedGlobalCounter = counter;
    }

    public abstract void execute();
}

// 子类1:直接用父类的静态变量,不用传参
class Step01 extends BaseStep {
    @Override
    public void execute() {
        System.out.println("Step01执行 | 全局配置:" + sharedGlobalConfig + " | 全局计数器:" + sharedGlobalCounter);
    }
}

// 子类2:修改静态变量后,所有子类都会看到变化
class Step02 extends BaseStep {
    @Override
    public void execute() {
        sharedGlobalCounter++;
        System.out.println("Step02执行 | 全局配置:" + sharedGlobalConfig + " | 全局计数器:" + sharedGlobalCounter);
    }
}

// 主类:调用父类静态方法初始化
public class StateDemo {
    public static void main(String[] args) {
        // 一步搞定所有子类的共享变量初始化
        BaseStep.initSharedVars("全局共享配置V2.0", 0);

        BaseStep step1 = new Step01();
        BaseStep step2 = new Step02();

        step1.execute(); // 计数器0
        step2.execute(); // 计数器1
        step1.execute(); // 计数器1(因为静态变量被修改了)
    }
}

方案3:抽离共享状态类(最优雅,适合复杂共享逻辑)

如果共享变量比较多、逻辑复杂,或者不想用静态变量(避免全局状态的副作用),可以把共享变量抽成一个独立的类,然后把这个类的实例传递给每个子类——这样所有子类共享同一个状态实例,修改时所有子类都会同步:

// 单独的共享状态类:封装所有共享变量和操作
class SharedState {
    private String config;
    private int counter;

    public SharedState(String config, int counter) {
        this.config = config;
        this.counter = counter;
    }

    // getter/setter,封装变量操作
    public String getConfig() { return config; }
    public void setConfig(String config) { this.config = config; }
    public int getCounter() { return counter; }
    public void incrementCounter() { this.counter++; }
}

// 抽象父类:持有共享状态实例
abstract class BaseStep {
    protected SharedState sharedState;

    public BaseStep(SharedState sharedState) {
        this.sharedState = sharedState;
    }

    public abstract void execute();
}

// 子类1:通过sharedState访问共享变量
class Step01 extends BaseStep {
    public Step01(SharedState sharedState) {
        super(sharedState);
    }

    @Override
    public void execute() {
        System.out.println("Step01执行 | 配置:" + sharedState.getConfig() + " | 计数器:" + sharedState.getCounter());
    }
}

// 子类2:修改共享状态,所有子类同步
class Step02 extends BaseStep {
    public Step02(SharedState sharedState) {
        super(sharedState);
    }

    @Override
    public void execute() {
        sharedState.incrementCounter();
        System.out.println("Step02执行 | 配置:" + sharedState.getConfig() + " | 计数器:" + sharedState.getCounter());
    }
}

// 主类:创建共享状态实例,传递给所有子类
public class StateDemo {
    public static void main(String[] args) {
        // 初始化共享状态实例
        SharedState sharedState = new SharedState("组合式共享配置", 0);

        // 所有子类共用同一个sharedState
        BaseStep step1 = new Step01(sharedState);
        BaseStep step2 = new Step02(sharedState);

        step1.execute(); // 计数器0
        step2.execute(); // 计数器1
        step1.execute(); // 计数器1
    }
}

为什么不推荐主类直接改protected变量?

protected的可见性是“包内+子类”,如果主类和父类不在同一个包,根本访问不了;就算在同一个包,直接修改会破坏封装——父类的变量逻辑被分散到主类里,后期维护时你根本不知道哪里改了这些变量,很容易出bug。上面的方案都遵循了封装原则,主类只负责初始化,子类只负责使用,父类(或独立状态类)负责管理变量逻辑。

内容的提问来源于stack exchange,提问作者Mr. Knackwurst

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 07:47:06