动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。不改变接口的前提下,增强所考虑的类的性能。
何时使用:
1)需要扩展一个类的功能,或给一个类增加附加责任。
2)需要动态的给一个对象增加功能,这些功能可以再动态地撤销。
3)需要增加一些基本功能的排列组合而产生的非常大量的功能,从而使继承变得 不现实。
实例场景:
例如买了一个新手机,有时想给手机添加点装饰于是贴膜、贴图片等小挂件来增加手机美感
传统实现方式:
在平常实现方式中我们一般定义一个手机类接口,接口中定义好贴膜、添加贴图的方法代码如下:
namespace Designer.DecorationPattern
{
public interface IPhone
{
string Name { get; set; }
void AddStick();
void AddPicture();
}
public class Phone:IPhone
{
/// <summary>
/// 手机名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 添加贴膜
/// </summary>
public void AddStick()
{
Console.WriteLine($"开始给{Name}手机贴膜");
Console.WriteLine($"给{Name}手机贴膜完毕");
}
/// <summary>
/// 添加贴图
/// </summary>
public void AddPicture()
{
Console.WriteLine($"开始给{Name}手机贴图片");
Console.WriteLine($"给{Name}手机贴图片完毕");
}
}
public static class SignUp
{
static void Main(string[] args)
{
Console.WriteLine("================给苹果手机添加贴膜=========================");
Phone applePhone = new Phone {Name = "苹果手机"};
//给苹果手机贴膜
applePhone.AddStick();
//给苹果添加图片
applePhone.AddPicture();
Console.WriteLine("================给安卓手机添加贴膜=========================");
Phone andriodPhone = new Phone { Name = "安卓" };
//给安卓手机贴膜
andriodPhone.AddStick();
//给安卓添加图片
andriodPhone.AddPicture();
Console.ReadLine();
}
}
}
运行结果:
该方法是传统实现方式但是如果我想添加一个给手机去除贴膜的方法;那么我们是不是需要在接口中在添加给方法;然后在继承类中实现在方法呢;如果这样我们在不断添加新的方法;那么我们还要不断给接口添加方法,然继承类实现方法;那么这样做起来是不是违反设计模式开闭原则呢。
装饰者模式:
装饰者模式就是在保持原有类或者功能不变的情况下添加类或组件来达到扩展功能的需求。
看下面代码实现:
namespace Designer.DecorationPattern
{
public interface IPhone_Decoration
{
string Name { get; set; }
}
public class PhoneDecoration : IPhone_Decoration
{
/// <summary>
/// 手机名称
/// </summary>
public string Name { get; set; }
}
/// <summary>
/// 装饰接口
/// </summary>
public interface IDecoration
{
void AddFunction(IPhone phone);
}
public class Stick : IDecoration
{
/// <summary>
/// 添加贴膜
/// </summary>
public void AddFunction(IPhone phone)
{
if (phone != null)
{
Console.WriteLine($"开始给{phone.Name}手机贴膜");
Console.WriteLine($"给{phone.Name}手机贴膜完毕");
}
}
}
public class Picture : IDecoration
{
/// <summary>
/// 添加贴图
/// </summary>
public void AddFunction(IPhone phone)
{
if (phone != null)
{
Console.WriteLine($"开始给{phone.Name}手机贴图片");
Console.WriteLine($"给{phone.Name}手机贴图片完毕");
}
}
}
public class DecorationWay
{
private static void Main(string[] args)
{
IDecoration stickDecoration = new Stick();
IDecoration pictureDecoration = new Picture();
Console.WriteLine("================给苹果手机添加贴膜=========================");
Phone applePhone = new Phone { Name = "苹果手机" };
//给苹果手机贴膜
stickDecoration.AddFunction(applePhone);
//给苹果添加图片
pictureDecoration.AddFunction(applePhone);
Console.WriteLine("================给安卓手机添加贴膜=========================");
Phone andriodPhone = new Phone { Name = "安卓" };
//给安卓手机贴膜
stickDecoration.AddFunction(andriodPhone);
//给安卓添加图片
pictureDecoration.AddFunction(andriodPhone);
Console.ReadLine();
}
}
}
运行结果:
上面通过添加IDecoration接口以及实现类来达到给手机添加装饰同时又没有修改核心功能。