【问题标题】:The best way to pass Java reference down the chain of objects将 Java 引用沿对象链向下传递的最佳方式
【发布时间】:2012-05-05 16:32:39
【问题描述】:

让我们考虑一个这样的对象链:

Earth->Continent->Country->City->name

我们还要考虑Earth.classpublic static void main(String[] args)

当应用程序使用命令行选项执行时,例如Barcelona,在不引入中间参数的情况下将其传递给 City 对象的最佳方法是什么?

对象是在程序执行期间的不同阶段创建的。

我们应该将name 变量设为静态还是使用 IoC,例如 Spring 或 Google Guice? 还有其他选择吗?

欢迎提出任何想法。

【问题讨论】:

    标签: java parameter-passing


    【解决方案1】:
    • 我最喜欢 IOC 来完成这项任务。让 IOC 在构建 City 时传递依赖。
    • 替代方案:使用静态服务注册表,可以查询其值。城市可以从服务注册中心获得它的名字。
    • 替代方案:在您的层次结构上实现复合模式,包括一个函数,例如 find,它可以返回城市。然后你只需要查询并设置earth.find(BarcelonaID).setName(args[0]);

    PicoContainer 中 IoC 解决方案的示例:

    PicoContainer container = new DefaultPicoContainer();
    container.addComponent(Earth.class);
    container.addComponent(Continent.class);
    container.addComponent(Country.class);
    container.addComponent(City.class, new ConstantParameter(cityName));
    
    City barcelona = container.getComponent(City.class);
    

    【讨论】:

    • 谢谢,克里斯托弗。 IoC 看起来不错,但最初需要基础设施才能飞起来,说到 Spring 和 Guice。我想知道这样的设置是否合理,只是将几个命令行参数传递到正确的位置:)
    • @IvanBalashov 基础设施是最小的。请参阅示例。
    【解决方案2】:

    您可以自上而下构建数据结构——大陆构建城市,或自下而上——main 构建城市并将其传递给国家,或使用某种组合。 DI 倾向于后者。

    public static void main(String... argv) {
      // Bottom up.
      City city = new City(/* args relevant to city */);
      Country country = new Country(city, /* args relevant to country */);
      Continent continent = new Continent(country, /* args relevant to continent */);
      Planet planet = new Planet(continent, /* args relevant to planet */);
    }
    
    class City {
      City(/* few parameters */) { /* little work */ }
    }
    class Country {
      Country(/* few parameters */) { /* little work */ }
    }
    ...
    class Planet {
      Planet(/* few parameters */) { /* little work */ }
    }
    

    这可能比自上而下更简洁:

    public static void main(String... argv) {
      // Top down.
      Planet earth = new Planet(
        /* all the parameters needed by Earth and its dependencies. */);
    }
    class Planet {
      Planet(/* many parameters */) { /* lots of work */ }
    }
    ...
    

    DI 人士认为,自下而上的构造会导致代码更易于维护和测试,但您不需要 DI 框架来使用它。

    【讨论】:

    • 谢谢,迈克。幸运的是,需要在 Earth 类之外构建对象。否则,这不会很有趣:)
    • @IvanBalashov,我主张在外面建造它们。
    • @MikeSamuel 我不认为在它们应该存在的地方创建对象是一个好主意。一个国家需要知道哪些城市属于它,如果你把这些知识放在Country 类之外,那么你就违反了对象封装
    • @GETah,当你建设国家时,你会告诉它其中有哪些城市。
    • @MikeSamuel 我明白了,这样做,你仍然暴露了只有 Country 才应该知道的细节,不是吗?
    【解决方案3】:

    在我看来,这是Visitor 模式的最佳用例。 基本上,应该有一个类Parameters 应该包含所有参数。每个需要一组参数的对象都可以使用Parameters 类访问。然后,该对象可以将参数传递给它的子代,这些子代知道要使用哪些参数以及如何使用。 在您的情况下,可以这样做:

    public interface IParameterized{
       public void processParameters(Parameters param);
    }
    
    public class Earth implements IParameterized{
       public Earth(){
          // Create all countries here and store them in a list or hashmap 
       }
       public void processParameters(Parameters param){
          // find the country you want and pass the parameters to it
          country.processParameters(param);
       }
    } 
    
    public class Country implements IParameterized{
       public Country(){
          // Create all cities that belong to this country
       }
       public void processParameters(Parameters param){
          // find the city you want and pass the parameters to it
          city.processParameters(param);
       }
    } 
    
    public class City implements IParameterized{
       public City(){
          // Create city...
       }
       public void processParameters(Parameters param){
          // Do something with the parameter
       }
    }
    

    编辑 要连接点,可以通过以下方式使用:

    public static void main(String... argv) {
         Parameters params = new Parameters();
         // Populate params from the command line parameters
         Earth earth = new Earth();
    
         // Earth takes the responsibilty of processing the parameters
         // It will delegate the processing to the underlying objects in a chain
         earth.processParameters(params);
    }
    

    作为旁注,您还可以查看Chain Of Responsibility 设计模式

    【讨论】:

    • 谢谢,GETah。但是我们仍然需要在某个地方保存 IParameterized 对象,并将其传递给其他对象,这意味着所有引用都应该在一个地方可用。我想知道我们是否能找到真正解耦的东西:)
    • @IvanBalashov 参数将在 main 中创建并沿链传递,请看我的编辑
    • 是的,但你必须拥有EarthCity 以及main() 中可用的其他对象,这些对象在我的案例中是在其他地方创建的...
    • @IvanBalashov 只有Earth 对象将在main() 中创建,其他对象将在不同的地方创建:Countries 可以在其他任何地方创建,但应该是来自Earth 的引用等等开。
    • @IvanBalashov 请看我的编辑。我在代码中添加了构造函数,让您了解应该在哪里创建不同的对象
    猜你喜欢
    • 2011-03-20
    • 2021-03-09
    • 2019-04-16
    • 2014-10-14
    • 2011-09-19
    • 1970-01-01
    • 1970-01-01
    • 2013-09-15
    • 2010-12-08
    相关资源
    最近更新 更多