设计模式问题:关于拥有重复资源的对象的设计
如图所示,我需要在一块画板上画若干的元素,这些元素可以是图片,图形或者文字等,每个对象都有自己的x,y坐标以及width,height等,并且每个对象都实现了自己的Draw方法,所以我要画出这么一张图的话,只需要遍历一个对象的集合,逐个调用对象的Draw方法即可。
现在问题也是如图所示,我要在这个画板上绘制许多相同的图,只不过位置不同(或者别的属性有所差别),但它们都是同一个位图文件(如“avatar.jpg”)来的,所以我要生成上图的显示效果,就要new四个对象,每个对象各自去加载avatar.jpg,相当于生成了四个Image,造成了浪费,其实比较节省的方案是只生成一个Image,在不同的地方绘制四次。
大家一起讨论讨论如何设计。在开始前请考虑下面这个因素:
avatar.jpg可能发生改变,我创建了一个监视线程去监视它,如果它发生了改变,就会产生一个Reload的动作,Reload之后,我希望依旧只存在一个Image对象。
模式尽量要简单易懂点,谢谢。
[解决办法]
有点像原型模式
[解决办法]
或都是享元,不过原型更像。
[解决办法]
用装饰模式:把基本图片作为基类,其他属性如x,y坐标以及width,height等都放到继承的装饰类里面来,这样就一个图片了。
[解决办法]
什么狗屁设计模式,纯扯淡
这个设计很简单
多出一层来就行了
你现在只有一类Object,他既负责存储资源,又负责绘制
其实,需要两类对象
一类是用来描述资源的,可以是图片文字
另一类负责绘制,需要指定一个资源,并且规定位置
这个跟即时战略游戏太像了
就是同种单位,你制造了多个实体,多个实体共享一个外观模型,却具有不同的位置和状态
[解决办法]
方法:
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方法就好了。