对象消费模式

时间:2013-06-07 10:12:20

标签: c# oop object-lifetime

我试图解决一个特定的问题,事实上,这是一个更普遍问题的例子。让我们说我们有几个对象,其中一个对象依赖于另一个:

Bitmap AnImage;   // Several instances of this object are possible: an image is loaded; then is discarded; then a new image is loaded, and so on.

Public class PixelSelection    
{
     string GenericAttribute;
      int X;
      int Y;

     public PixelSelection(string myAttribute, int x, int y)
     {
          GenericAttribute = myAttribute;
          X = x;
          Y = y;
     }
}

第二个目标:

  1. 以这种方式创建:new PixelSelection(“Whatever”,AnImage.Width, AnImage.height)所以它取决于AnImage对象;
  2. 它公开了主应用程序可以订阅的事件。
  3. 每个类只需要一个实例,并且两个对象都是由用户按需创建的:如果没有Bitmap实例,则不能使用PixelSelection,但是当用户需要与PixelSelection对象进行交互时,就会出现对实例的需求。

    我正在处理的问题是如何使PixelSelection与Bitmap保持同步;这些是我正在考虑的可能情景:

    1. 将PixelSelection声明为主窗体的属性,然后在每次创建新位图时将其实例化。这需要每次都进行新的事件注册,并使代码容易出错,因为每次需要创建新的Bitmap时,开发人员需要记住实例化在不同代码段中引用的新PixelSelection对象。
    2. 在开始时实例化PixelSelection对象,对所有Bitmap实例使用相同的对象,仅在代码中真正使用的位置更新其属性X和Y.这需要一个没有x和y参数的新构造函数,因为没有Bitmap可用,并且代码用于管理PixelSelection中的不一致性,当尝试在没有正确初始化的情况下对实例执行操作时。
    3. 使用包含Bitmap和PixelSelection对象的包装器对象作为属性,仅用于在分配位图时强制正确创建或更新PixelSelection对象。这对我来说听起来非常不自然(或肮脏),因为这个包装器不适合解决方案域模型,它只是解决一个非常具体问题的解决方法。
    4. 创建一个派生自Bitmap的类,将PixelSelection作为属性,以显而易见的方式管理其生命周期。这可能导致超级胖的类充满了一堆对象,这些对象不是为了模拟某些东西而只是为了解决对象生命周期需求和使用模式。
    5. 我起草的四个暂定场景在抽象方面非常不同,并尝试使用不同的工具集;更糟糕的是,我觉得他们可以证明我对OO模型的理解不足,显示出对象生命周期问题和面向对象建模的混淆。请有人帮我确定解决问题的最佳方法是什么,就最佳实践而言,解决方案是正确的答案?感谢。

3 个答案:

答案 0 :(得分:0)

  

我正在处理的问题是如何使PixelSelection与Bitmap保持同步

为什么不将Bitmap的引用添加到PixelSelection

public class PixelSelection    
{
     string GenericAttribute;
     int X;
     int Y;
     private readonly Bitmap bitmap;

     public PixelSelection(string myAttribute, int x, int y, Bitmap bitmap)
     {
          GenericAttribute = myAttribute;
          X = x;
          Y = y;
          this.bitmap = bitmap;
     }
}

答案 1 :(得分:0)

对于一个非常抽象的问题,不可能给出一个绝对的答案,你并不是真的在一个定义的问题上寻找具体的建议,而是一个可能或可能与你的问题无关的一般指南。

对于这个特定场景,我无法真正看到PixelSelection类和Bitmap之间的“强制连接”。你的PixelSelection需要一个宽度和一个高度,但就是这样,它不需要一个Bitmap,如果不需要它,那么添加一个额外的依赖是不好的。

另外,您声明只需要1个位图实例和1个PixelSelection实例。那么创建那些作为静态元素/单例并在必要时更新它们并且一切都会好的吗?

从更一般的角度来看,从纯OO设计的角度来看解决方案3可能是明智之举。当然,除非在您的特定场景中使用任何其他方法更有意义。或者将位图引用添加到PixelSelection ...

如果没有完整的图片,并且知道我们需要什么类型的限制,那么就无法给出明确的答案。

答案 2 :(得分:0)

我找到了一个适合我的解决方案。我理解真正的要求是拥有一个代码段,我可以执行任何操作以保持两个对象的同步而不会产生不必要的依赖关系;答案是:事件。我的解决方案是创建一个类(单例),其中一个方法完全负责在PictureBox控件中加载图片;该类有一个方法来执行触发事件的更新:

/*
 * Load the picturebox in the control 
 */
        public   void UpdatePictureBox( Bitmap BitmapToBeLoaded, PictureBox CurrentPictureBox)
        {
            /*
             * If the Bitmap or the picturebox are null there is nothing to update: so exit keeping loaded the previous image
             */
            if (BitmapToBeLoaded == null) return ;

            CurrentPictureBox.Image = BitmapToBeLoaded;                // Assign the Bitmap to the control
            /*
             *  When loading, adapt the control size to the image size to avoid any distortion
             */
            CurrentPictureBox.Width = BitmapToBeLoaded.Width;          // Adapth width of the control size
            CurrentPictureBox.Height = BitmapToBeLoaded.Height;        // Adapth height of the control size    

            /*
             * Publish events defensively: Book .Net Components, pag. 108
             */
            try
            {
                if (null != ImageUpdated) ImageUpdated();    // Fire the event
            }
            catch
            {
            }
            return ;           
        }

这样,在新图像可用之后执行的所有操作都是在订阅事件时执行的,在一段代码中很容易找到并记录。我并不认为这是最好的解决方案;但令我满意的是设计看起来更干净。