使配置可用于所有类

时间:2011-05-17 11:54:00

标签: java oop singleton

我正在编写一个小型Web服务器,它需要一个配置文件,其中包含各种不同的选项:运行多少个线程,哪个类处理每个文件扩展名,哪个文件默认显示等等等等等等等等等等。向前。为了表示这一点,我将配置文件解析为包含所有这些设置的Configuration对象,主类保存此对象。
但是,几乎每个服务器级别都需要配置数据 - 类中类的类......

我的问题是,在这里使用的最佳做法是什么?我应该将配置作为许多类的参数并来回传递吗?我应该把它变成单身吗?还有其他我没有看到的解决方案吗?

9 个答案:

答案 0 :(得分:4)

使用Guice! Guice是一个依赖注入框架,它有效地取代了你对new关键字的使用。您可以在模块中定义对象绑定,如下所示:

bind(Configuration.class).to(MySpecificConfiguration.class);
bind(WebServer.class).to(MySpecificWebServerImplementation.class);

然后,不要直接新建WebServer,而是让Guice为你做这件事:

WebServer ws = Guice.createInjector(yourModule).getInstance(WebServer.class);

这将为你神奇地创造MySpecificWebServerImplementation。如果MySpecificWebServerImplementation定义如下:

public class MySpecificWebServerImplementation {
    @Inject 
    public MySpecificWebServerImplementation(Configuration configuration) {
    }
}

然后MySpecificWebServerImplementation将自动获得配置,您不必担心传递它。

答案 1 :(得分:2)

虽然Singletons由于各种原因不再受到许多专业人士的青睐 - 我认为使用Ssingleton仍有一个很好的用例。

然而 - 问问自己,网络服务器的要求是否真的需要服务器所有方面的单一通用配置。如果是的话 - 他们很快就有可能改变? 例如 - 假设您的服务器托管3个网站。现在你被要求对其中一个设置带宽限制 - 你将如何配置它?

我真的很喜欢一个好的单例 - 虽然在多线程环境中初始化它时你必须要考虑整个线程安全问题(虽然听起来你不会有这个问题,因为你不会有多个线程在初始化之前。

请注意,单身人士居住在ClassLoader内,如果您有多个ClassLoader(例如,您加载的每个.war),您将拥有此“{{1}的多个副本}}”。

考虑服务器的所有方面,如果它非常简单 - Singleton将为您节省很多麻烦 - 并且会使代码更易于维护和读取。 正如在一个或两个答案中已经提到的 - 依赖注入是Singleton的一个很好的替代方案 - 它们可以帮助您简化JUnits。

关于JUnit的一个注释,我理解(还没有尝试)Singleton可以允许你在测试运行期间替换实际的实现,所以你仍然可以为不同的场景创建不同的JUnit测试用例修改您的Mockit是可测试的。

答案 2 :(得分:1)

使它成为一个单身人士似乎是一个合理的解决方案。我认为将配置作为参数传递给其他类构造函数或方法调用是错误的,因为这会污染方法参数并使它们变得不必要地复杂。

如果你决定制作一个单例,那么我建议你设计一种机制,你可以将配置的新实例注入单例类,这样单例就不会让你的单元测试很难运行。 / p>

答案 3 :(得分:1)

传递Configuration的实例会给代码增加许多不必要的混乱。 Singleton是一个好主意或添加某种 Manager 类,它提供所有这些共享资源,如配置数据。

如果你选择单身人士,请考虑实施枚举模式:

public enum Config{ DATA;

   private int value1;
   private int value2;
   private int value3;
   public load(File configFile) {
     // some magic to store the values
   }
   public int getValue1() {return value1;}
   public int getValue2() {return value2;}
   public int getValue3() {return value3;}
}

您可以在代码中的任何位置使用它:

int property = Config.DATA.getValue1();

答案 4 :(得分:1)

如果您在Java中执行此操作,我会将所有配置放在Spring中,然后使用Application Context查找设置或只是将它们注入您的bean。春天擅长这种事情。

答案 5 :(得分:1)

我们将您的属性设置为系统属性。这些是由SystemProperties类访问的。
这个类是final,带有一个私有构造函数,属性只能通过静态方法访问,所以从技术上来说它是一个Singleton。它本身包含在commons.jar中,其他每个项目都依赖于它。

所以没有必要传递任何东西,因为设置可以直接在您需要的地方使用。

答案 6 :(得分:0)

我肯定会让配置持有者类成为Singleton!我是Singleton实例的经典用例。

答案 7 :(得分:0)

配置没有,但最好有一个单例对象ServerManager。太多全局可访问的对象有点令人困惑。配置应由“组件”拥有:

ServerManager.getServerManager.getConfigurationComponent(Configuration.class);

ServerManager应该在开始时创建和读取配置对象。离开之前保存并关闭它。

如果您在任何课程中多次使用它,请将其存储为私人最终字段。

答案 8 :(得分:0)

我经常使用它。我做了多个产品安装,但它们并不总是在同一个地方。但是,产品的安装,集成和实施通常是相同的。因此,为了弥补这一点,我编写了一个配置属性类,它查看了config.properties文件。您将进入并首先将属性文件修改为您需要的位置,值等等。然后使用config类编译该类,并使用该应用程序执行该操作。

以下示例。 config.properties文件

import_dir=c:\\temp\\test\\import
export_dir=c:\\temp\\test\\export
system_dir=c:\\temp\\test\\system
username=mainman
role=admin
domain=
server=
hostname=

等...

然后我在班上创建了一个班级。

public static class Config {

    private static Properties defaultProps = new Properties();
    static {
        try {
            FileInputStream in = new FileInputStream("config.properties");
            defaultProps.load(in);
            in.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static String getProperty(String key) {
        return defaultProps.getProperty(key);
    }
}

我相信你也可以创建一个独立课程,但这也可以。

然后在我的方法内部,或在主类中,我得到我需要的值,并将它们分配给我需要的任何东西。然后我可以将它们传递给需要它们的相应方法。

domain = Config.getProperty("domain");
server = Config.getProperty("server");
hostname = Config.getProperty("hostname");

非常酷!

我也在多个操作系统上使用它。