动态对象与Singleton的特定操作

时间:2012-09-28 16:59:26

标签: java singleton

我想知道这种设计是对还是错,或两者兼而有之 我有一个带有几个组件(对象)的应用程序,每个组件都有一个配置(标志,功能等) 在任何时候,我都想从物体中找回配置 为此,我这样做了:

class ConfigRetriever {
    public String getConfigString() {
        String configString = "";   
        configString += "component 1 flag : "+component1.getFlag()+"\n";
        configString += "component 2 flag : "+component2.getFlag()+"\n";
        // ...
        return( configString );
    }
}

其他地方,需要配置时:

class SomeClass {
    public void someMethod() {
        ConfigRetriever configRetriever = new ConfigRetriever(); 
        String configString = configRetriever.getConfigString();
            // Do some stuff with configString...
    }
}

我是对象编程的新手,为一个特定的动作创建一个对象(ConfigRetriever)仍然感觉很奇怪(即使对象能够做其他的事情)。
我也谈到了单身模式,有些事情是这样的:

String configString = ConfigRetriever.getInstance().getConfigString();

这是一个简洁的线条,但由于对象在应用程序结束之前一直停留在内存中,我真的不知道什么是对的,什么是错的。

我的设计会更好吗?怎么样 ?为什么?

更新
谢谢您的回答。我觉得我的问题有点乱,我错过了我要求的内容 整个配置和组件故事在这里作为我正在处理的那种情况的一个例子。这是快速而脏的代码,我应该警告你。真正的问题是:“创建一个对象只需一次(或有时)访问其中一种方法是否合适?” 那么,阅读你的答案并再次思考它,似乎正确的答案是“这取决于你的目标,课程,责任等等......”
我想在我的对象中存储信息吗?不能是静态的方法 使用永久内存的单例是一个问题吗?大多数情况下,因为我认为你必须有充分的理由在全局状态下维护内存中的对象。所以,大多数时候:没有单身人士。

最后,创建一个用于实例化某个对象的类是一个问题吗?它不是,去吧! : - )

3 个答案:

答案 0 :(得分:1)

我认为没有必要在这里使用单身。

为单个操作创建对象并不奇怪,但如果经常调用该方法可能效率不高。我认为你能做的最好就是使用dependency injection

class SomeClass {
    private final ConfigRetriever retriever;
    public SomeClass(ConfigRetriever retriever) {
        this.retriever = retriever;
    }
    public void someMethod() {
        // use this.retriever here
    }
}

答案 1 :(得分:1)

还没有人提到static方法。典型的Java模式是使用静态方法,您可以在没有类实例的情况下进行分类。类似的东西:

class ConfigRetriever {
   public static String getConfigString() {
      StringBuilder sb = new StringBuilder();
      sb.append("component 1 flag : ").append(component1.getFlag()).append('\n');
      sb.append("component 2 flag : ").append(component2.getFlag()).append('\n');
      // ...
      return sb.toString();
   }
}

因此,您可以执行以下操作:

// call the static method on the class, not on an instance
String configString = ConfigRetriever.getConfigString();

由于您没有实例,因此无法在ConfigRetriever内存储状态。我不确定component1component2对象来自何处。

注意我转换了您的getConfigString()方法,以使用比StringBuilder()方法 更高效的+=类实际上在内部使用多个 StringBuilder类。

答案 2 :(得分:0)

几个问题 -
答:您的原始代码有一个返回void的方法,名为getConfigString - 这应该是固定的。
B.此外,还不清楚ConfigRetriever类中提供组件的位置。
C.您可以选择以下选项:

1.具有ConfigProvider类层次结构,它将与您的组件层次结构匹配 -
如果您有名为ComputerComponent的类,您将拥有匹配的ComptuerConfigProider。
您可以考虑在Component类中使用ConfigProider getConfigProvider方法。

public abstract class Component {
   public abstract ConfigProvider getConfigProvider()'
}

然后具体的类看起来像:

public class ComputerComponent extends Component {
   public ConfigProvider getConfigProvider() { 
       return new ComputerConfigProvider(this);
   }
}




2.类似于第一个的解决方案,但是有一个ConfigProvider类,其中包含添加配置组件的方法。
例如,假设ConfigurationProvider仅包含键和值的映射。
在这种情况下,您的代码可以如下所示:

public class ConfigProvider {

    private Map<String,String> internalMap = new HashMap<String,String>();
    public String getConfigProvider() {
      //Return a string representation of the internal map
    }

    public ConfigProvider addConfigElement(String key,String value) {
        map.put(key,value); 
        return this;
    }
}

public class ComputerComponent extends Component {
    private int memory;
    private String cpu;
    public ConfigProvider getConfigProvider() {
       ConfigProvider configProvider = new ConfigProvider();
       return configProvider.addConfigElement("memory",Integer.toString(memory)).
       addConfigElement("cpu",cpu);
    } }




3.如果你仍然想使用单线 - 由于你的配置取决于组件状态,有一个配置提供者单线是错误的,除非你把getConfigProvider变成一个“无状态”方法 -

String getConfigString(Component component)

但在这种情况下,您可能会考虑不使用单线,而只是使用静态方法,代码如下:

public class ConfigurationProvider {
   public static String getConfigString(Component component) {
     StringBuilder sb = new StringBuilder();
     //Append the component values to the string builder
     return sb.toString();
   }
}