【问题标题】:Why strange naming convention of "AlertDialog.Builder" instead of "AlertDialogBuilder" in Android为什么在Android中使用“AlertDialog.Builder”而不是“AlertDialogBu​​ilder”的奇怪命名约定
【发布时间】:2012-08-04 16:55:42
【问题描述】:

为什么不

AlertDialogBuilder builder = new  AlertDialogBuilder(this);
builder.setTitle("foo");

而不是

AlertDialog.Builder builder = new  AlertDialog.Builder(this);
builder.setTitle("foo");

更新:我想知道这种写作/组织背后的原因

【问题讨论】:

标签: android android-alertdialog


【解决方案1】:

根据Javadocs,嵌套类(在本例中为静态嵌套类)通常用于三件事:

  1. 对只能一起使用的类进行逻辑分组。
  2. 增加封装。
  3. 提高代码的可读性和可维护性。

第 3 点是许多开发人员使用静态嵌套类的原因之一。我们以 Android 开发中的ViewHolder pattern 为例。在ListAdapter 中,我们可以通过管理ViewHolder(或类似名称的内部类)中每个列表元素的内容来轻松缓存列表。在这种情况下,很容易注意到这个特定的ViewHolder 仅适用于这个类,当我们更改这个时,我们不会更改每一个。这意味着我们不需要List1ViewHolderList2ViewHolder、...、ListNViewHolder。每个List-type 元素都可以有自己的ViewHolder

第 2 点与这一点不太相关,因为我们正在处理静态内部类(Builder 就是这样)。但在这种情况下,它会阻止内部类的元素被外部类访问。

第 1 点在这里很重要,这就是为什么我把它留到最后。想想你将使用AlertDialog.Builder 的情况。我可以 100% 肯定地保证,您每次使用 AlertDialog.Builder 时,都会在 AlertDialog 的构建/创建/处理中。因此,这意味着AlertDialog.Builder 的每次使用都与AlertDialog 的工作方式相关。 (这在某种程度上与第 3 点相关;在一个文件中维护两个类比将它们分开更容易。)

与第 1 点和第 3 点类似,但也有其自身的特点,即通过将 Builder 保留在 AlertDialog 中,我们不会污染 android.app 包命名空间。我们仍然只在其中保留AlertDialog;但Builder 隐藏在其中。

Android 不是唯一这样做的系统; MotiveWave SDK 也这样做,Adobe Access 和 eBay SDK(我没有链接)也是如此。我也相信Java EE 也使用这种方法。您还将see it often in Enum types,这又是因为第 1 点所述的原因。

现在,您问我们为什么使用AlertDialog.Builder 而不是new AlertDialog(),并从对象而不是构建器构建它。这里的答案与 Java 和其他面向对象编程语言中常见的factory method pattern 相同。值得注意的是(来自维基百科),原因有以下三个:

  1. 对象的创建会阻止其重用,而无需大量重复代码。
  2. 创建对象需要访问不应包含在组合类中的信息或资源。
  3. 生成对象的生命周期管理必须集中进行,以确保应用程序中的行为一致。

这些解释得很好;他们反对代码重复(能够在一个类中处理所有创建功能)、未经授权的访问(糟糕的封装实践)和一致的构造行为。此处未列出的还有code readability

我怀疑——凭直觉——AlertDialog 是一个非常耗费资源的过程。它会暂停部分操作系统,保持其他部分运行,必须加载系统资源等等。正如this answer 的详细信息,我们不想提供对外部类的直接访问(在这种情况下为AlertDialog)。这允许Builder 正确处理所有资源密集型操作。它还使我们不必处理操作系统开发人员考虑过的深奥情况,但我们没有。

因此,总而言之,这实际上是一种相当普遍的设计模式,但不是具有真正明确定义的含义。相反,它是为了易于使用、理解和可维护性。您提到了对上述设计考虑的担忧;我不会太担心这一点。请记住,静态内部类应该始终仅与它们的外部类相关,你应该没问题。

【讨论】:

  • 那么为什么不直接设计成AlertDialog dialog = new AlertDialog(); 呢?
  • 它有几个目的,特别是防止错误的访问和以最好的方式处理资源。我已经在我的回答中详细说明了这一点。
  • @Howard new AlertDialog() 将没有任何意义,没有标题,没有消息,没有任何东西。但是您不必设置所有内容(例如,您通常不需要超过 1 个按钮)。因此,Builder 模式允许您指定您需要的内容,然后让您创建()对话框。这是 GoF 书中的经典 Builder Pattern 案例。
【解决方案2】:

BuilderAlertDialog 类中的静态内部类。所以要创建一个Builder类对象,你需要调用AlertDialog.Builder

因为没有像 AlertDialogBu​​ilder 这样的类,所以你不能这样做。

如果你愿意,你也可以像下面这样使用。

Builder builder = new Builder(this);
builder.setTitle("foo");

但要像这样使用,您需要将 Builder 类导入到您的类中,例如

import android.app.AlertDialog.Builder;

而不仅仅是

import android.app.AlertDialog;

一个简单的例子

class A{
     static class B{}
}

你不能使用

AB obj = new AB();

你必须使用

A.B obj = new A.B();

希望你现在清楚了。

【讨论】:

  • 这背后有什么设计考虑吗?这种设计模式很少见,我从未在其他 Java SDK 中使用过。
  • 我只看到使用构建器的两个好处:1) 有助于避免使用带有许多参数的构造器。 2) 有助于避免大量数据验证,并允许将其移动到名为 build 的单一方法中。
【解决方案3】:

我会尽力为你澄清这种组织的背后。

首先,Builder 是 AlertDialog 类中的一个类。 为什么要在另一个类中创建一个类?如果我想向现有类添加更多功能并且不认为从设计的角度来看应该扩展类,我个人只创建嵌套类。我敢肯定有人会对此争论不休,因为有很多不同的方法可以为类添加更多功能。然而嵌套类可能比其他类更受欢迎(对于某些人来说)。

这是oracles 对嵌套类的看法。

如果我发现嵌套类使代码更易于维护和直观,我只会使用它。

在这种情况下,我相信 Google 的人发现,与 AlertDialog.Builder 相比,不是创建一个名为 AlertDialogBu​​ilder 的新类,而是因为两者产生相同的结果;一个对话框,在屏幕上显示一些信息,带有一些按钮。两者之间的唯一区别(我认为)是您可以在 AlertDialog.Builder 上设置积极、中性和消极按钮(这为类提供了更多功能,但没有必要更多地扩展类,再次个人意见)。

最后重要的是代码可以正常工作(希望没有任何错误)、可维护、可读且直观。你的问题没有明确的答案,因为人们对这个话题有不同的看法。

我希望这会有所帮助。

【讨论】:

    【解决方案4】:

    用于构造AlertDialog Object 的方法称为Builder Pattern,以增强可读性。当你想构造一个新对象但这个对象需要很多属性来创建它时,就像传递给构造函数的参数太多(超过 4 个)一样,你会感到困惑。如果您想了解更多关于构建器模式的信息,我认为answer 将满足您的需求。 AlertDialog 的构造与链接中的示例非常相似:

    @Override 
    public Dialog onCreateDialog(Bundle savedInstanceState) {
    return new AlertDialog.Builder(getActivity())
               .setMessage("Do you really want to exit?")
               .setCancelable(false)
               .setNegativeButton("No", 
                        new DaialogInterface.onClickListener() {
                                public void onClick(DialogInterface dialog, 
                                int id) {
                                        ((AlertDialogActivity) getActivity())
                                                    .continueShutdown(false);
                                    }
    
                            })
               .setPositibeButton("Yes", 
                        new DialogInterface.onClickListener()) {
                            public void onClick(
                                    final DialogInterface dialog, int id) {
                                        ((AlertDialogActivity) getActivity())
                                                    .continueShutdown(true);
                                    }
                        }).onCreate();
    }
    

    此方法返回 Dialog 对象,询问用户是否要退出应用程序,正如您所见,通过调用具有太多参数的构造函数来创建 AlertDialog 对象没有任何意义。想象一下如果AlertDialog 有这样的构造函数:

    AlertDialog ad = new AlertDialog(getActivity(), "Do you really want to exit?", 
                                     false, "No", .... )//and the list goes on 
    

    将此方法与onCreateDialog 方法进行比较,我认为onCreateDialog 方法获胜对吗?

    【讨论】:

      猜你喜欢
      • 2017-02-01
      • 2019-05-28
      • 2013-02-27
      • 2011-08-20
      • 2012-11-09
      • 2011-10-06
      • 2022-06-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多