-1

我正在为一组将在多个项目中使用的方法寻找一种设计模式,所以我正在用它们制作一个“库”。

起初我想把它们都设为静态,这样它们就可以被 Library.methodName() 调用,就是这样。我做到了,并意识到我为每个可以设置一次然后在类中使用的方法传递了几个常量值。(这个常数值在项目之间变化)

现在我想到了一个必须用这个值实例化的类,并通过对象访问方法而不是每次都传递值,但是我想防止每次都创建“库”类的对象,所以我想到了辛格尔顿。

我确实用所有这些做了一个单例,但是我set首先需要为类变量做一个显式的,但是这种方法要求程序员现在必须在使用方法之前设置值,这将使它失败最终肯定会,即使是我自己。

一直在做Singleton.getInsance(value1, value2).method(...)是不可能的,我更喜欢我最初的方法。另外,我不能为这个变量定义一个“默认”值,它们必须被设置。

是否有一种设计模式可以帮助我拥有一个可以用给定值初始化而不必一直传递它们的单例?

还是我应该坚持我最初的方法并让程序员一直传递这些值?

或任何其他选项,任何适合的设计模式或其他任何东西也可以工作。

谢谢

4

6 回答 6

0

我应该坚持我最初的方法并让程序员一直传递这些值吗?

我能看到的唯一替代方法是为包含和设置所有强制值的上下文提供一个构造函数。如果可以的话,我会避免使用有状态的单例。

如果调用者想避免多次创建对象,他们可以根据需要将其设为单例,但您不应强迫他们使用单例。

于 2012-08-29T08:37:18.683 回答
0

您尝试创建的库完全违反了面向对象设计的原则。您不应该创建函数/方法库。相反,您应该创建一个包含状态和行为的类库。

于 2012-09-07T12:52:37.110 回答
0

这种方式对你来说舒服吗?

public class AreaCalculator {
  private int length = 10;
  private int width = 10;
  private static final AreaCalculator areaCalculator = new AreaCalculator();

  private AreaCalculator() {
    // TODO Auto-generated constructor stub
  }

  public static AreaCalculator getInstance() {
    return areaCalculator;
  }

  public AreaCalculator fillLength(int length) {
    this.length = length;
    return getInstance();
  }

  public AreaCalculator fillWidth(int width) {
    this.width = width;
    return getInstance();
  }

  public AreaCalculator fillAll(int length, int width) {
    this.length = length;
    this.width = width;
    return getInstance();
  }

public int calculateArea() {
    if (!isInit()) {
        throw new RuntimeException("Should Init first!");
    }
    return length * width;
}

public boolean isInit() {
    // add something
    return true;
}

测试代码

public class TestMain {

  public static void main(String[] args) {
    int result = AreaCalculator.getInstance().fillWidth(20).calculateArea();
    System.out.println("10*20=" + result);
    result = AreaCalculator.getInstance().fillWidth(10).fillLength(10).calculateArea();
    System.out.println("10*10=" + result);
    result = AreaCalculator.getInstance().fillAll(10, 30).calculateArea();
    System.out.println("10*30=" + result);
  }

**

使用配置界面。

**

ConfigInf(库端)

public interface ConfigInf {

    public static String F_LENGTH = "length";
    public static String F_WIDTH = "width";

    public String getProperty(String key);

}

ConfigFactory(库端)

public class ConfigFactory {

    private static ConfigInf config = null;

    public static void init(ConfigInf config) {
        ConfigFactory.config = config;
    }

    public static ConfigInf getConfig() {
        if (config == null) {
            throw new NullPointerException("Config should be init first");
        }
        return config;
    }
}

ClientConfig(客户端)

public class ClientConfig implements ConfigInf {

    String value = "10";

    @Override
    public String getProperty(String key) {
        // read configFile
        if (ConfigInf.F_LENGTH == key) {
            return value;
        } else {
            return "100";
        }

    }

    public void update() {
        value = "100";
    }

}

AreaCalculatorWithConfig(lib 端)

public class AreaCalculatorWithConfig {
    private int length = 10;
    private int width = 10;
    //
    private static final AreaCalculatorWithConfig areaCalculator = new AreaCalculatorWithConfig();

    private AreaCalculatorWithConfig() {
        // TODO Auto-generated constructor stub
    }

    public static AreaCalculatorWithConfig getInstance() {
        return areaCalculator;
    }

    public int calculateArea() {
        ConfigInf config = ConfigFactory.getConfig();
        length = getInt(config.getProperty(ConfigInf.F_LENGTH));
        width = getInt(config.getProperty(ConfigInf.F_WIDTH));
        return length * width;
    }

    public static int getInt(String value) {
        return Integer.parseInt(value);
    }
}

TestMainWithConfig(客户端)

public class TestMainWithConfig {
    public static void main(String[] args) {
        // init;
        ClientConfig config = new ClientConfig();
        ConfigFactory.init(config);
        //
        System.out.println("Before update:"
                + AreaCalculatorWithConfig.getInstance().calculateArea());
        config.update();
        System.out.println("After update:"
                + AreaCalculatorWithConfig.getInstance().calculateArea());
    }
}
于 2012-08-29T09:11:18.800 回答
0

根据您的要求,您可以使用Factory pattern基于传递的常量创建库实例然后 Singleton创建实例。

于 2012-08-29T09:11:20.290 回答
0

我只需将初始化添加到 Config 类,在那里它可以可靠地初始化一次。然后应用程序的其余部分依赖于正确完成初始化。也许您可能希望避免因异常而重复初始化。诀窍是确保只有一个点负责填充单例,无论是通过设计还是通过异常的蛮力。日志记录的配置非常相似。不过,也不算太奇怪。

于 2012-08-29T10:11:00.853 回答
0

或者,由于这些值在项目之间而不是在项目内部发生变化,因此您的“库”可以读取一个配置文件,为您提供这些值value1, value2,这样调用代码就不需要每次都提供它们。

这将是一种懒惰的阅读(在第一次调用时进行),因此您还可以确保该库在使用之前已初始化。如果该文件当然不存在,那么您可能希望抛出未经检查的异常。

于 2012-08-29T08:40:48.900 回答