装饰模式
装饰模式(Decorator),动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
1.装饰模式的特点
(1)装饰对象和真实对象有相同的接口。这样客户端对象就能以和真实对象相同的方式和装饰对象交互。
(2)装饰对象包含一个真实对象的引用(reference)
(3)装饰对象接受所有来自客户端的请求。它把这些请求转发给真实的对象。
(4)装饰对象可以在转发这些请求以前或以后增加一些附加功能。这样就确保了在运行时,不用修改给定对象的结构就可以在外部增加附加的功能。在面向对象的设计中,通常是通过继承来实现对给定类的功能扩展。
2.适用性
(1)需要扩展一个类的功能,或给一个类添加附加职责。
(2)需要动态的给一个对象添加功能,这些功能可以再动态的撤销。
(3)需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实。
(4)当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。
所有设计模式总结请参考:http://blog.csdn.net/chr23899/article/details/46999267
所有设计原则总结请参考:http://blog.csdn.net/chr23899/article/details/46999401
首先来看下具体的效果图
从效果图中我们可以看出用户在生成草原时可以用八中选择: 不装饰、太阳、白云、小花、太阳+白云、太阳+小花、白云+小花、全装饰。如果采用创建子类的方式,则需要七个子类来完成相应的功能,这就会出现’子类爆炸’的现象。如果装饰模式则可以动态的添加装饰而避免此类现象的发生。
先看下具体的装饰类图效果
类的详细设计代码如下:
//定义草原抽象类
public abstract class GrassLand
{
//抽象方法 用于重写
public abstract void draw(PictureBox pic, Graphics g);
}
//定义初始子类LandModel
public class LandModel : GrassLand
{
//实现抽象函数
public override void draw(PictureBox picbox_img, Graphics g)
{
//蓝天
g.FillRectangle(Brushes.Blue, 0, 0, picbox_img.Width, picbox_img.Height);
//绿草
g.FillPie(Brushes.Green, 0, picbox_img.Height / 4 * 3, picbox_img.Width * 2, picbox_img.Height / 2, 180, 270);
}
}
//定义装饰者类
public class Decorator : GrassLand
{
//定义草场对象
private GrassLand land;
//构造函数赋初值
public Decorator(GrassLand l)
{
land = l;
}
//重写draw方法
public override void draw(PictureBox pic, Graphics g)
{
if (land != null)
land.draw(pic, g);
}
}
//绘制太阳
public class DrawSun : Decorator
{
public DrawSun(GrassLand land)
: base(land)
{
}
public override void draw(PictureBox pic, Graphics g)
{
base.draw(pic, g);
addsun(pic, g);
}
//完成要装饰的内容
private void addsun(PictureBox picbox_img, Graphics g)
{
//太阳
g.FillEllipse(Brushes.Red, picbox_img.Width / 8, picbox_img.Height / 8, picbox_img.Width / 7, picbox_img.Width / 7);
}
}
//绘制白云
public class DrawCloud : Decorator
{
public DrawCloud(GrassLand land)
: base(land)
{
}
public override void draw(PictureBox pic, Graphics g)
{
base.draw(pic, g);
addcloud(pic, g);
}
//完成要装饰的内容
private void addcloud(PictureBox picbox_img, Graphics g)
{
//白云
g.FillEllipse(Brushes.GhostWhite, picbox_img.Width / 8 * 3, picbox_img.Height / 6, picbox_img.Width / 7, picbox_img.Height / 9);
g.FillEllipse(Brushes.GhostWhite, picbox_img.Width / 8 * 6, picbox_img.Height / 6, picbox_img.Width / 7, picbox_img.Height / 9);
g.FillEllipse(Brushes.GhostWhite, picbox_img.Width / 16 * 9, picbox_img.Height / 4, picbox_img.Width / 7, picbox_img.Height / 9);
}
}
public class DrawFlower : Decorator
{
public DrawFlower(GrassLand land)
: base(land)
{
}
public override void draw(PictureBox pic, Graphics g)
{
base.draw(pic, g);
addflower(pic, g);
}
//完成要装饰的内容
private void addflower(PictureBox picbox_img, Graphics g)
{
//小花
g.FillEllipse(Brushes.Pink, picbox_img.Width / 9, picbox_img.Height - 10, 10, 8);
g.FillEllipse(Brushes.Pink, picbox_img.Width / 7, picbox_img.Height - 20, 10, 8);
g.FillEllipse(Brushes.Pink, picbox_img.Width / 5, picbox_img.Height - 30, 10, 8);
g.FillEllipse(Brushes.Pink, picbox_img.Width / 3, picbox_img.Height - 28, 10, 8);
g.FillEllipse(Brushes.Pink, picbox_img.Width / 16 * 15, picbox_img.Height - 45, 10, 8);
g.FillEllipse(Brushes.Pink, picbox_img.Width / 16 * 13, picbox_img.Height - 58, 10, 8);
g.FillEllipse(Brushes.Pink, picbox_img.Width / 16 * 11, picbox_img.Height - 15, 10, 8);
g.FillEllipse(Brushes.Pink, picbox_img.Width / 16 * 9, picbox_img.Height - 27, 10, 8);
g.FillEllipse(Brushes.Pink, picbox_img.Width / 16 * 7, picbox_img.Height - 39, 10, 8);
}
}
3.在装饰者模式中各个角色有:
(1)抽象构件(GrassLand)角色: 给出一个抽象接口,以规范准备接受附加责任的对象。
(2)具体构件(LandModel)角色: 定义一个将要接收附加责任的类。
(3)装饰(Decorator)角色: 持有一个构件(GrassLand)对象的实例,并定义一个与抽象构件接口一致的接口。
(4)具体装饰(DrawSun、DrawCloud和DrawFlower)角色: 负责给构件对象 ”贴上“附加的责任。
4.装饰模式的优点:
(1)Decorator模式与继承关系的目的都是要扩展对象的功能,但是Decorator可以提供比继承更多的灵活性。
(2)通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。
源程序下载地址:http://download.csdn.net/detail/chr23899/8925611
原文出处:http://blog.csdn.net/chr23899 转发请说明