内存有效的子类化方式

时间:2013-01-07 09:53:09

标签: java android

尝试为此提出一个有意义的问题标题是棘手的。我会解释我到底要做什么。

我创建了一个Android图形库,可以构建一个可能很大的Path个对象列表。我现在需要为每个Path附加一些额外的数据。为此,我简单地将Path(称为PathSubclass)子类化,以提供额外的扩展数据字段。在一般用例中,只有极少数Path个对象实际上会有额外的数据集。例如,可能有ArrayList几千Path秒,但只有少数人有额外的数据。在我开发库时,我希望附加到每个Path的额外数据量可能会大幅增加。我很欣赏这可能是过早的优化,但是我担心,当很少填充额外的数据并且使用相当大的该对象集合时,将对象子类化为包含一些额外的数据是没有效率的。

我想做的可能是ExtendedPathData类,与我的Path子类分开。因此,每个Path子类仅因需要mExtendedData成员而略有膨胀,在许多情况下,null成员将Path,除了那些需要的View个极少的对象附加数据。我认为这类似于通常使用setTag()方法将其他数据附加到{{1}}的方式。

我还应该考虑其他任何方法,不管出于什么原因这样做会更好吗?

2 个答案:

答案 0 :(得分:4)

您可以使用合成而不是继承。

创意1

PathData类可能包含对PathExtendedPathData的引用:

// encapsulate properly in your code, this is
// just a short sample
class PathData {
  public Path path;
  public ExtendedPathData data;
}

这使您可以将data成员设置为null。每个PathData实例的大小始终为两个引用。当ExtendedPathData中的成员数增加时,实际内存消耗仅会增加到具有非空PathData的{​​{1}}个实例。

创意2

您可以通过使用具有两个实现的接口来删除另一个引用:

data

由您自行决定是否确实有两个实现值得代码,因为您需要一个工厂方法来决定使用哪种实现。每个实例一个 4字节引用...

更多内容

如果interface PathData { Path path(); ExtendedPathData data(); } final class NullPathData implements PathData { Path path; public Path path() { return path; } public ExtendedPathData data() { return null; } } final class ExtendedPathData implements PathData { Path path; ExtendedPathData data; public Path path() { return path; } public ExtendedPathData data() { return data; } } 不可变可能存在许多相等的实例,您也可以通过公开使用实例的静态工厂方法来池化它们pool 而不是公共构造函数。

如果你有Effective Java by Joshua Bloch,这里有更详细的解释提示(在更一般的背景下):

  • 第1项考虑使用静态工厂方法而不是构造函数
  • 第16项偏爱继承的构成

答案 1 :(得分:2)

不是整个继承点,可以在下面的容器中存储Path的子类吗?

ArrayList<Path> pathList;

pathList.add(new Path());
pathList.add(new PathPlusPlus());

或者我不明白这个问题?

要消除丑陋的isinstanceof调用,正如@assylias所建议的那样,你可以在你的基类中添加一个getter来返回扩展数据。在基类本身中它将返回null,在子类中它将返回相关数据。