实现常量对象的最佳方法是什么?

Dav*_*ton 1 c++ java design-patterns coding-style

首先,我应该说"恒定对象"一词可能不太正确,可能已经意味着与我的想法完全不同,但这是我能想到的最好的术语来描述我所说的内容.

所以基本上我正在设计一个应用程序,我遇到的东西似乎可能有一个现有的设计模式,但我不知道它是什么或搜索什么,所以我将描述它是什么我是试图做,我正在寻找有关实施它的最佳方法的建议.

让我们说你有一节课:

public class MyClass {
    private String name;
    private String description;
    private int value;

    public MyClass(String name, String description, int value) {
        this.name = name;
        this.description = description;
        this.value = value;
    }

    // And I guess some getters and setters here.
}
Run Code Online (Sandbox Code Playgroud)

现在让我们说你事先知道只会说这个类的3个实例,并且数据也是预先知道的(或者至少会在运行时从文件中读取,并且确切的文件名是事先知道的).基本上我得到的是数据在运行时(一旦设置好)就不会改变.

起初我以为我应该在某处声明一些静态常量,例如

public static final String INSTANCE_1_DATA_FILE = "path/to/instance1/file";
public static final String INSTANCE_2_DATA_FILE = "path/to/instance2/file";
public static final String INSTANCE_3_DATA_FILE = "path/to/instance3/file";
public static final MyClass INSTANCE_1 = new MyClass(getNameFromFile(INSTANCE_1_DATA_FILE), getDescriptionFromFile(INSTANCE_1_DATA_FILE), getValueFromFile(INSTANCE_1_DATA_FILE));
public static final MyClass INSTANCE_2 = new MyClass(getNameFromFile(INSTANCE_2_DATA_FILE), getDescriptionFromFile(INSTANCE_2_DATA_FILE), getValueFromFile(INSTANCE_2_DATA_FILE));
public static final MyClass INSTANCE_3 = new MyClass(getNameFromFile(INSTANCE_3_DATA_FILE), getDescriptionFromFile(INSTANCE_3_DATA_FILE), getValueFromFile(INSTANCE_3_DATA_FILE));
Run Code Online (Sandbox Code Playgroud)

显然,现在,只要我想使用3个实例中的一个,我就可以直接引用常量.

但我开始认为可能有一种更清洁的方法来处理这个问题,我想到的下一件事就是:

public MyClassInstance1 extends MyClass {
    private static final String FILE_NAME = "path/to/instance1/file";

    public String getName() {
        if (name == null) {
            name = getNameFromFile(FILE_NAME);
        }
        return name;
    }

    // etc.
Run Code Online (Sandbox Code Playgroud)

}

现在,只要我想使用MyClass的实例,我就可以使用我想要的那个

private MyClass myInstance = new MyClassInstance2();
Run Code Online (Sandbox Code Playgroud)

或者甚至更好的做法是让他们成为单身人士而且只做:

private MyClass myInstance = MyClassInstance3.getInstance();
Run Code Online (Sandbox Code Playgroud)

但我不禁想到这也不是处理这种情况的正确方法.我是否在思考这个问题?我应该在某个地方有一个switch语句,例如

public class MyClass {
    public enum Instance { ONE, TWO, THREE }

    public static String getName(Instance instance) {
        switch(instance) {
        case ONE:
            return getNameFromFile(INSTANCE_1_DATA_FILE);
            break;
        case TWO:
            etc.
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

谁能告诉我实现这个的最佳方法?请注意,我已经用Java编写了示例代码,因为这是我最强的语言,但我可能会用C++实现该应用程序,所以目前我更多的是寻找与语言无关的设计模式(或者仅仅是某人告诉我选择我已提到的一个简单的解决方案.

mdm*_*dma 5

如果您希望值保持不变,那么您将不需要setter,否则代码可以简单地更改常量中的值,使它们不是很稳定.在C++中,你可以只声明实例const,虽然我仍然摆脱了setter,因为有人总是可以抛弃const.

该模式看起来没问题,尽管每次请求创建新实例时,常量都不常见.

在java中,您可以创建"智能"的枚举,例如

public enum MyClass {
    ONE(INSTANCE_1_DATA_FILE),
    TWO(INSTANCE_2_DATA_FILE),
    //etc...

    private MyClass(String dataFile)
    {
       this(getNameFromDataFile(dataFile), other values...)
    }

    private MyClass(String name, String data, etc...)
    {
       this.name = name;
       // etc..
    }

    public String getName()
    {
        return name;
    }
}
Run Code Online (Sandbox Code Playgroud)

在C++中,您将使用私有构造函数创建MyClass,该构造函数接受初始化所需的文件名和其他任何内容,并static const在MyClass中为每个实例创建成员,并使用私有构造函数为值创建新的MyClass实例.

编辑:但现在我看到的情况我不认为这是一个好主意有静态值.如果ActivityLevel的类型是应用程序的基础,那么您可以将不同类型的活动级别枚举为常量,例如java或字符串枚举,但它们只是占位符.实际的ActivityDescription实例应来自某种数据访问层或提供者.

例如

enum ActivityLevel { LOW, MED, HIGH  }

class ActivityDescription
{
    String name;
    String otherDetails;
    String description; // etc..
    // perhaps also
    // ActivityLevel activityLevel;

    // constructor and getters
    // this is an immutable value object
}

interface ActivityDescriptionProvider
{
    ActivityDescription getDescription(ActivityLevel activityLevel);
}
Run Code Online (Sandbox Code Playgroud)

如果需要,您可以使用静态实现提供程序,或者使用ActivityDescription实例的枚举,或者更好的是从文件加载的ActivityLevel到ActivityDescription的Map,从spring配置中获取等等.主要的一点是使用接口来获取给定ActivityLevel的实际描述将应用程序代码与系统中如何生成这些描述的机制分离.它还可以在测试UI时模拟界面的实现.您可以使用模拟实现来强调UI,这是使用固定静态数据集无法实现的.