装饰图案浪费内存

Posted

技术标签:

【中文标题】装饰图案浪费内存【英文标题】:Decorator pattern wasting memory 【发布时间】:2012-01-17 23:56:48 【问题描述】:

我的这个基类具有以下接口:

abstract class Base

  abstract public object Val
  
    get;
  

对于任何派生类,Val 的值必须在对象创建时指定。 问题是:我如何制作派生类来做到这一点(希望在编译时)? 我尝试添加一个构造函数:

abstract class Base

  public Base(object value)
  
    val = value;
  

  private object val;

  ...

但正如您所见,我必须声明一个私有字段来在其中存储值(因为 Value 是只读的)。 出现问题是因为我想使用 GoF 设计模式中引入的装饰器/包装器模式为派生类添加某种效果。但是因为我已经在 Base 类中声明了该字段,所以装饰器会一直保存相同数据的副本,我最终会浪费内存。

【问题讨论】:

装饰器是一个持有另一个对象的对象,因此您显然需要两个对象的内存。这正是您的解决方案所需的内存。如果这不适合您,您可能误用或误解了装饰器模式。你到底想解决什么问题? 如果我在 Base 类中只定义属性(而不是字段),那么装饰器实际上不必存储 Base 成员的任何其他副本。 装饰器不存储任何基本成员的副本。它只是存储对装饰对象的引用!? 它也必须从基类继承才能具有相同的接口。还是我错了? 您的应用程序是否真的内存不足?许多应用程序无需担心为此进行优化。 【参考方案1】:

试试这个:

abstract class Base 

    public Base(object val)
    
        this.Val = val;
    

    public object Val  get; private set; 

这样,您的派生类就不需要自己的字段:

public class Derived : Base

    public Derived(object val) : base(val)  

【讨论】:

@AtoMerZ 请注意,这仍然在基类中有一个字段;简单地说 - 编译器对我们隐藏它。自动实现的属性具有编译器生成的支持字段。【参考方案2】:

如果是装饰器,则没有字段:

public override object Val 
    // add any decoration effects here if needed
    get  return tail.Val; 

tail 是你正在装饰的东西。


但是,听起来您的意思是继承(而不是装饰)-如果是这样:

abstract class BaseClass 
    protected BaseClass(object val) ...

class ConcreteType : BaseClass 
    public ConcreteType(object val)
        : base(val)  

这里的基类甚至可以处理存储等。

【讨论】:

也许我不太明白。 Base 类有一个字段,因为装饰器继承了 Base 类,所以装饰器也是如此。我可以覆盖 Val 属性,但该字段仍保留在内存中。 @AtoMerZ 我很困惑......如果你不希望基类有一个字段,那么就不要有一个字段......让派生类担心它。如果基础没有该字段,它也不需要构造函数 - 只要有一个 public abstract object Value get; 就可以了...... 正如我在问题中所说,派生类必须初始化val。所以我不得不为基类提供一个构造函数来初始化val。这意味着我需要为该属性分配内存(因为我忘记了私有集是解决方案)。 你好像把装饰器和代理混淆了 @ivowiblo 不,我认为不会。装饰器一种对象包装模式。是什么让你觉得我把它弄糊涂了?

以上是关于装饰图案浪费内存的主要内容,如果未能解决你的问题,请参考以下文章

PHP CLI - 检测我的内存浪费在哪里

csharp 设计图案的结构,装饰

哪一个更可能浪费更少的内存,一个大内存管理器或几个小内存管理器? [关闭]

结构对齐可能会浪费内存?

Java内存使用量测试 看看我们天天在用的JVM到底浪费了多少内存资源

解决JavaScript中构造函数浪费内存的问题!