【问题标题】:Objects consumption pattern物品消费模式
【发布时间】:2013-06-07 10:12:19
【问题描述】:

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

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. 它公开了主应用程序可以订阅的事件。

每个类只需要一个实例,并且两个对象都是由用户按需创建的:您不能在没有 Bitmap 实例的情况下使用 PixelSelection,但是当用户需要与 PixelSelection 对象交互时,就会出现对实例的需求。

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

  1. 将 PixelSelection 声明为主窗体的属性,然后在每次创建新位图时实例化它。这每次都需要新的事件注册,并且使代码容易出错,因为每次需要创建新的位图时,开发人员都需要记住在不同的代码部分中实例化一个新的 PixelSelection 对象。
  2. 在开始时实例化 PixelSelection 对象,对所有 Bitmap 实例使用相同的对象,仅在代码中真正使用它的地方更新其属性 X 和 Y。这需要一个不带 x 和 y 参数的新构造函数,因为没有可用的位图,并且在尝试在没有正确初始化的情况下对实例执行操作时管理 PixelSelection 使用中的不一致性的代码。
  3. 使用具有 Bitmap 和 PixelSelection 对象作为属性的包装对象,仅用于在分配 Bitmap 时强制正确创建或更新 PixelSelection 对象。这对我来说听起来很不自然(或肮脏),因为这个包装器不适合解决方案域模型,它只是解决非常具体问题的一种解决方法。
  4. 创建一个派生自 Bitmap 的类,将 PixelSelection 作为属性,以显而易见的方式管理其生命周期。这可能会导致超胖类被填充一堆对象,这些对象不是为了建模,而只是为了解决对象生命周期的需求和使用模式。

我草拟的四个试探性场景在抽象上非常不同,并尝试使用不同的工具集;更糟糕的是,我觉得他们可以证明我对 OO 模型的理解不足,显示出对对象生命周期问题和面向对象建模的困惑。请有人帮我确定解决问题的最佳方法是什么,以及为什么就最佳实践而言,该解决方案是正确的答案?谢谢。

【问题讨论】:

    标签: c# oop object-lifetime


    【解决方案1】:

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

    为什么不将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;
         }
    }
    

    【讨论】:

      【解决方案2】:

      对一个非常抽象的问题给出绝对答案是不可能的,您实际上并不是在寻找针对已定义问题的具体建议,而是寻找可能与您的问题相关或不相关的一般指导方针。

      对于这种特定情况,我无法真正看到 PixelSelection 类和位图之间的“强制连接”。您的 PixelSelection 需要一个宽度和一个高度,但仅此而已,不需要位图,如果不需要,添加额外的依赖项会很糟糕。

      您还声明您只需要 1 个位图实例和 1 个 PixelSelection 实例。因此,将它们创建为静态元素/单例,并在必要时更新它们,一切都会好起来的?

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

      如果不了解完整的情况,也不知道我们满足哪些类型的限制,就不可能给出明确的答案。

      【讨论】:

        【解决方案3】:

        我找到了适合我的解决方案。我知道真正的要求是有一个代码部分,我可以在其中执行任何所需的操作,以使两个对象保持同步,而不会产生不必要的依赖关系;答案是:事件。我的解决方案是创建一个类(单例),其中一个方法完全负责将图片加载到其 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 ;           
                }
        

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-12-07
          • 1970-01-01
          • 2014-10-08
          • 2018-12-18
          • 1970-01-01
          • 1970-01-01
          • 2013-01-18
          • 1970-01-01
          相关资源
          最近更新 更多