12

为什么不

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

代替

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

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

4

4 回答 4

25

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

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

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

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

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

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

Android 并不是唯一这样做的系统。MotiveWave SDK也这样做,Adobe Access 和 eBay SDK(我缺少链接)也是如此。我也相信Java EE也使用这种方法。您还会在 Enum types 中经常看到它,这反过来又是由于第 1 点所涵盖的原因。

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

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

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

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

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

于 2012-08-10T05:54:15.300 回答
13

Builder是AlertDialog类中的静态内部类。因此,要创建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();

希望你现在清楚了。

于 2012-08-04T16:57:15.283 回答
1

我会试着清理你在这种组织背后的真相。

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

这是关于嵌套类的Oracle观点。

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

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

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

我希望这有帮助。

于 2012-08-15T19:37:50.870 回答
0

用于构造AlertDialogObject 的方法称为 Builder Pattern 以增强可读性。当你想构造一个新对象但这个对象需要很多属性来创建它时,就像传递给构造函数的参数太多(超过 4 个)一样,你会感到困惑。如果您想了解有关构建器模式的更多信息,我认为此答案将满足您的需求。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方法获胜的方法进行比较,对吗?

于 2014-10-27T16:30:32.613 回答