0

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

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. 创建一个从具有 PixelSelection 作为属性的 Bitmap 派生的类,以显而易见的方式管理其生命周期。这可能会导致超胖的类被一堆对象填充,这些对象不是为了建模,而只是为了解决对象生命周期的需求和使用模式。

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

4

3 回答 3

0

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

为什么不添加对Bitmapinto的引用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;
     }
}
于 2013-06-07T10:31:42.550 回答
0

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

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

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

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

如果没有完整的图片并且不知道我们满足什么样的限制,就不可能给出明确的答案。

于 2013-06-07T10:34:23.323 回答
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 ;           
        }

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

于 2013-06-27T09:19:34.430 回答