3

在为 Android 开发时,我遇到了一个Bitmap类。我觉得奇怪的是这个类没有公共构造函数,而是提供了createBitmap具有完全相同目的的静态函数。

在语法上没有优势:

Bitmap bm = new Bitmap(10, 10);
Bitmap bm = Bitmap.createBitmap(10, 10);

我见过其他类也这样做,其中等效的静态函数通常命名为newInstance. 这是什么原因?

4

4 回答 4

6

您所描述的称为工厂方法。它的存在是因为它提供了获取符合特定接口但可能具有不同底层实现的对象的能力。

对于(一个完全任意且微不足道的)示例,工厂方法可能会选择为您提供 LinkedList 对象而不是 ArrayList 对象,因为您指定的初始大小可能在 LinkedList 中具有性能优势。

但是两个列表实现都符合 IList 接口,因此结果对象作为 IList 返回。

于 2013-08-01T18:14:51.730 回答
1

在第一种情况下,您需要实例化特定类型。在第二个中,您将其留给实现者来决定返回哪种类型。

我不熟悉 Bitmap,但另一个例子是 EnumSet。你打电话时:

EnumSet<SomeEnum> set = EnumSet.noneOf(SomeEnum.class);

静态工厂方法根据枚举中的项目数量使用不同的实现,以便在所有情况下都尽可能高效。

底层代码返回RegularEnumSet小枚举的 a 或JumboEnumSet大枚举的 a。构造函数不可能进行这种上下文优化。

public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) {
    Enum[] universe = getUniverse(elementType);
    if (universe == null)
        throw new ClassCastException(elementType + " not an enum");

    if (universe.length <= 64)
        return new RegularEnumSet<>(elementType, universe);
    else
        return new JumboEnumSet<>(elementType, universe);
}
于 2013-08-01T18:16:30.717 回答
1

这是工厂方法模式。

这样做的主要原因有两个:

  1. 它允许将来不总是每次都返回一个新实例。例如Integer.valueOf(int),如果值介于 -127 和 128 之间,将重新使用它已经创建的相同 Integer 对象。这是代码中最常见的 Integer 值,因此我们没有让 JVM 制作数千个相同实例的副本(其中每个都占用内存)并且可以重复使用相同的实例。

  2. 它允许静态方法在调用者不知道的情况下返回子类。如果将工厂方法与代理或适配器等其他设计模式相结合以返回类的修改版本,这将很有用。

于 2013-08-01T18:17:37.227 回答
0

编辑:这个问题是一些涵盖的内容:

工厂、抽象工厂和工厂方法

设计模式:工厂 vs 工厂方法 vs 抽象工厂

这就是工厂模式。重点是从静态类创建类,因此您可以隐藏类的编程细节(安全措施)。

资源:

http://www.oodesign.com/factory-pattern.html

意图:

创建对象而不向客户端公开实例化逻辑。通过通用接口引用新创建的对象

例子:

public class ProductFactory{
    public Product createProduct(String ProductID){
        if (id==ID1)
            return new OneProduct();
        if (id==ID2) return
            return new AnotherProduct();
        ... // so on for the other Ids

        return null; //if the id doesn't have any of the expected values
    }
    ...
}

另一个可靠的来源:

http://sourcemaking.com/design_patterns/factory_method

于 2013-08-01T18:19:09.257 回答