我们平时买煎饼,可以向其中加鸡蛋,也可以加香肠,但不管加多少不同的东西,都还是一个煎饼。在现实生活中,常常需要对现有产品增加新的功能或美化其外观,如房子装修,相片加框等,都是装饰模式的体现。
在软件开发过程中,有时想用一些现存的组件。这些组件可能只是完成了一些核心功能,为了满足新需要,并在不改变其结构的情况下,动态地扩展其功能,就可以用到装饰模式。
装饰模式的定义与特点
装饰模式的定义:在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式。
优点:
①装饰模式是继承的有力补充,比继承更灵活,在不改变原有对象结构的情况下,动态地给该对象扩展功能,即插即用。
②通过使用不同装饰类及这些装饰类的排列组合,可以实现不同的效果。
③装饰模式完全遵守开闭原则。
装饰模式的结构与实现
通常情况下,扩展一个类的功能会使用继承方式来实现,但继承耦合度较高,并且随着扩展功能的增多,子类会很膨胀。如果使用组合关系来创建一个包装对象,来包裹真实对象,并在保持真实对象的类结构不变的前提下,为其提供额外的功能,这就是装饰模式的目标。
装饰模式的结构
1.抽象构件:定义一个抽象接口以规范附加功能的对象。
2具体构件:被装饰者对象,实现抽象构件,通过具体装饰角色为其添加一些附加功能。
3.抽象装饰:继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。
4.具体装饰:实现抽象装饰的相关方法,并给具体构件对象添加附加的功能。
装饰模式结构图:
写法示例(以买煎饼为例):
定义抽象构件,确定要为煎饼做装饰:
public abstract class IJianBing
{
public abstract void Show();
}
然后我们定义具体构件,被装饰的煎饼对象:
public class JianBing : IJianBing
{
public override void Show()
{
Debug.Log("这是一个煎饼");
}
}
定义抽象装饰,以供具体装饰对象继承:
public abstract class AddFood : IJianBing
{
IJianBing Jb;
public AddFood(IJianBing jb)
{
Jb = jb;
}
public override void Show()
{
//子类重写实现不同装饰逻辑
Jb.Show();
}
}
定义具体装饰,实现一些具体的装饰对象:
public class AddEgg : AddFood
{
public AddEgg(IJianBing jb) : base(jb)
{ }
public override void Show()
{
Debug.Log("加个鸡蛋");
base.Show();
}
}
public class AddXiangChang : AddFood
{
public AddXiangChang(IJianBing jb) : base(jb)
{ }
public override void Show()
{
Debug.Log("加个香肠");
base.Show();
}
}
public class AddJiLiu : AddFood
{
public AddJiLiu(IJianBing jb) : base(jb)
{ }
public override void Show()
{
Debug.Log("加个鸡柳");
base.Show();
}
}
客户端调用代码:
//创建一个煎饼对象
JianBing aJb = new JianBing();
//要加鸡蛋,创建一个鸡蛋对象,修饰煎饼
AddEgg egg = new AddEgg(aJb);
//还要加香肠,创建一个香肠对象,修饰已经加了鸡蛋的煎饼
AddXiangChang xiangChang = new AddXiangChang(egg);
//还要加鸡柳,创建一个鸡柳对象,修饰已经加了鸡蛋、香肠的煎饼
AddJiLiu jiliu = new AddJiLiu(xiangChang);
jiliu.Show();
运行结果展示:
实现了子类的作用,但是却没有破坏类的层次结构,仅仅是将原类和新方法封装在了一起。
总结:
装饰模式能够具有这样的特性,主要还是在于它的结构。使用组合关系,获取原有对象的访问权,并添加自己的方法。
下期讲解——代理模式