Telescope构造函数的设计模式或依赖注入

时间:2016-11-15 11:29:27

标签: java android design-patterns dependency-injection dagger-2

我有一个 DownloadFile 类,具有以下属性

  1. 两(2)个必填参数
  2. 三(3)个可选参数
  3. 所有参数都是不可变的
  4. 1)当前设计(远程构造模式)

    构造

    DownloadFile (String name, String url, String from, String by, Boolean isDownloaded)
    

    必填参数:

    1. 名称
    2. URL
    3. 可选参数:

      1. 通过
      2. isDownloaded
      3. 我从 20 不同位置调用我的DownloadFile类(当用户单击列表上的按钮,任何已启动的活动,服务,推送通知,特定警报时,任何广播接收等)。

        new DownloadFile(name, url, from, by, false);
        
          

        问题:

             

        每当我想添加新参数时,我需要更改类+20个不同的呼叫位置

        例如,我想添加第三个必填参数( 尺寸

        新强制参数:

        1. 名称
        2. URL
        3. 尺寸
        4. 2)选项1(建筑师模式)

          存在构建器模式的良好解释here

          Joshua Bloch在Effective Java,第2版中说:

            

          在设计构造函数或静态工厂具有多个参数的类时,构建器模式是一个不错的选择。

               

          问题:

               

          问题依然存在,如果强制参数中有加法,我需要更改班级+20个不同的呼叫位置

          3)选项2(依赖注入 - Dagger2)

          Google建议避免dependency injection frameworks like Roboguice,而Dagger 2是Google建议的唯一DI。

          我之前没有使用和查看Dagger2,我发现basic tutorial手上的this answer by one of its founderhttps://brajeshwar.github.io/entities/

          问题:

          1. Dagger 2是否会解决这个不断增加的参数构造函数的问题? (下载文件代码示例会很棒)
          2. 此类要求的任何其他设计模式。

2 个答案:

答案 0 :(得分:1)

首先,您的示例不使用' telescoping构造函数'图案。伸缩构造函数的一个例子与你给定的代码有点一致,如下所示:

public DownloadFile(@NonNull String name, @NonNull String url) {
    this.name = name;
    this.url = url;
}

public DownloadFile(@NonNull String name, @NonNull String url, @NonNull String from) {
    this(name, url);
    this.from = from;
}

public DownloadFile (@NonNull String name, @NonNull String url, @Nullable String from, @Nullable String by, @Nullable Boolean isDownloaded) {
    this(name, url);
    this.from = from;
    this.by = by;
    this.isDownloaded = isDownloaded;
}

根据您的规范,您会遇到许多参数类型为String的问题,并且您无法指定这两者之间的差异:

//duplicate constructor signatures - won't compile
public DownloadFile(@NonNull String name, @NonNull String url, @NonNull String from) {
    this(name, url);
    this.from = from;
}

public DownloadFile(@NonNull String name, @NonNull String url, @NonNull String by) {
    this(name, url);
    this.by = by;
}

像Dagger这样的依赖注入框架不太可能有所帮助;依赖注入框架用于依赖项,您传递给DownloadFile的是参数

正如Effective Java中所建议的,构建器是一个很好的选择。如果您认为添加额外的强制参数会改变20个地方的签名,我不确定您是否完全理解了构建器模式。在使用构建器的位置,您只需手动添加必需参数setMandatoryParameter(String extraMandatoryParameter);。如果您需要额外的强制参数,您将始终必须执行某事

//old
new DownloadFile.Builder()
    .setName(String name)
    .setFrom(String from)
    .build();

//a wild mandatory parameter appears
new DownloadFile.Builder()
    .setName(String name)
    .setFrom(String from)
    .setExtraMandatoryParameter(String extraMandatoryParameter)
    .build();

也许你在考虑默认值 - 让我们说你有一个额外的强制性参数String但是你不想担心一直设置它,因为在大多数情况下它将是一个默认字符串"默认"。然后,您只需在构造函数中指定DownloadFile.Builder

public Builder() {
    this.extraMandatoryParameter = "default"
}

如有必要,您仍然可以覆盖默认值:

public Builder setExtraMandatoryParameter(String extraMandatoryParameter) {
    this.extraMandatoryParameter = extraMandatoryParameter;
    return this;
}

如果您使用的是Android Studio,则IDE甚至可以通过Replace constructor with builder选项为您执行此操作。

答案 1 :(得分:0)

在Effective Java 3rd Edition中,它还添加了JavaBeans模式。

具有必需参数的构造函数

public DownloadFile(String name, String url)
{
   this.name = name;
   this.url = url;
}

然后为每个可选字段添加setter:

public void setFrom(String from) { this.from = from; }
public void setBy(String by) { this.by = by; }
public void setIsDownloaded(Boolean isDownloaded) { this.isDownloaded = isDownloaded; }

但是@DavidRawson构建器的例子在我看来是最好的解决方案。 如Effective Java中所述

  

在这种模式中,您可以在许多调用中构造对象,

通常你想在构造函数调用之后拥有'真正的'对象。