设计模式有关问题:关于拥有重复资源的对象的设计

设计模式问题:关于拥有重复资源的对象的设计
如图所示,我需要在一块画板上画若干的元素,这些元素可以是图片,图形或者文字等,每个对象都有自己的x,y坐标以及width,height等,并且每个对象都实现了自己的Draw方法,所以我要画出这么一张图的话,只需要遍历一个对象的集合,逐个调用对象的Draw方法即可。


现在问题也是如图所示,我要在这个画板上绘制许多相同的图,只不过位置不同(或者别的属性有所差别),但它们都是同一个位图文件(如“avatar.jpg”)来的,所以我要生成上图的显示效果,就要new四个对象,每个对象各自去加载avatar.jpg,相当于生成了四个Image,造成了浪费,其实比较节省的方案是只生成一个Image,在不同的地方绘制四次。

大家一起讨论讨论如何设计。在开始前请考虑下面这个因素:

avatar.jpg可能发生改变,我创建了一个监视线程去监视它,如果它发生了改变,就会产生一个Reload的动作,Reload之后,我希望依旧只存在一个Image对象。

模式尽量要简单易懂点,谢谢。


------解决方案--------------------
有点像原型模式
------解决方案--------------------
或都是享元,不过原型更像。
------解决方案--------------------
用装饰模式:把基本图片作为基类,其他属性如x,y坐标以及width,height等都放到继承的装饰类里面来,这样就一个图片了。
------解决方案--------------------
什么狗屁设计模式,纯扯淡

这个设计很简单
多出一层来就行了

你现在只有一类Object,他既负责存储资源,又负责绘制

其实,需要两类对象
一类是用来描述资源的,可以是图片文字
另一类负责绘制,需要指定一个资源,并且规定位置

这个跟即时战略游戏太像了
就是同种单位,你制造了多个实体,多个实体共享一个外观模型,却具有不同的位置和状态
------解决方案--------------------
方法:
C# code
        private Image FillImage(Image img1, Image img2, ImagePosition[] positions)    //以BMP为例
        {
            MemoryStream ms1 = new MemoryStream();                                    //声明2个图片的流,类似指针
            MemoryStream ms2 = new MemoryStream();
            img1.Save(ms1, System.Drawing.Imaging.ImageFormat.Bmp);                    //把图片以内存BMP加载到流中
            img2.Save(ms2, System.Drawing.Imaging.ImageFormat.Bmp);
            int img1rowsize = img1.Size.Width * 3;                                    //计算行偏移 (* 3是RGB像素占位3个 如果是其他的格式需要改) 
            int img2rowsize = img2.Size.Width * 3;
            int img1offsetHeader = 35;                                                //BMP头的偏移量 好像是35
            int img2offsetHeader = 35;
            byte[] buffer = new byte[img2rowsize];                                    //创建缓冲

            foreach (ImagePosition aa in positions)                                    //遍历所有位置
            {
                int x = aa.X;                                                        //获取坐标
                int y = aa.Y;
                
                if(x > img1.Size.Width || y > img1.Size.Width) continue;            //溢出判断
                int xOffset = x * 3;                                                //计算行偏移量
                int buffercount = img2rowsize;
                if (xOffset > img1rowsize)                                            //计算x溢出
                {
                    buffercount -= xOffset - img1rowsize;                            //丢弃溢出
                    if (buffercount < 0)                                            //防止0读取
                    {
                        buffercount = 0;
                    }
                }
                
                //穷举img2中的每一行
                for (int i = 0, l = img2.Size.Height; i < l; i++)
                {
                    if (y + i > img1.Size.Height) break;                            //y溢出判断
                    //从img2中读取1行
                    int count = ms2.Read(buffer, img2offsetHeader + i * img2rowsize, buffercount);
                    //写入到img1中指定位置
                    int rowOffset = img1offsetHeader + y * img1rowsize;                //计算列偏移量
                    ms1.Write(buffer, rowOffset + xOffset, count);
                }
            }
            Bitmap img = new Bitmap(ms1);
            ms1.Dispose();
            ms2.Dispose();
            return img;
        }

------解决方案--------------------
“所以我要生成上图的显示效果,就要new四个对象,每个对象各自去加载avatar.jpg,相当于生成了四个Image,造成了浪费,其实比较节省的方案是只生成一个Image,在不同的地方绘制四次。”

——这个问题其实很简单,关键是理解清楚“引用”和“对象”。Image对象可以只有一个,new出来的这4个对象各保持一个指向此Image对象的引用就可以了。图片更新了以后,可以调用Image对象的Reload方法重新加载图像,再调用那些new出来的四个对象的Re-paint方法就好了。