可以使用装饰者模式来动态地给一个对象添加额外的职责。
装饰者模式以对客户透明的方式动态地给一个对象附加上更多的责任,装饰者模式相比生成子类可以更灵活地增加功能。
在装饰者模式中各个角色有:
抽象构件(Phone)角色:给出一个抽象接口,以规范准备接受附加责任的对象。
具体构件(AppPhone)角色:定义一个将要接收附加责任的类。
装饰(Dicorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。
具体装饰(Sticker和Accessories)角色:负责给构件对象 ”贴上“附加的责任。
优点:
装饰这模式和继承的目的都是扩展对象的功能,但装饰者模式比继承更灵活
通过使用不同的具体装饰类以及这些类的排列组合,设计师可以创造出很多不同行为的组合
装饰者模式有很好地可扩展性
缺点:装饰者模式会导致设计中出现许多小对象,如果过度使用,会让程序变的更复杂。
意图:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。
主要解决:一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。
何时使用:在不想增加很多子类的情况下扩展类。
如何解决:将具体功能职责划分,同时继承装饰者模式。
关键代码: 1、Component 类充当抽象角色,不应该具体实现。 2、修饰类引用和继承 Component 类,具体扩展类重写父类方法。
该实例基于WPF实现,直接上代码,下面为三层架构的代码。
一 Model
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 设计模式练习.Model.装饰者模式
{
//装饰抽象类:要让装饰完全取代抽象组件,所以必须继承Car
public abstract class AbstructCar : Car
{
public string Result { get; set; }
private Car car;
protected AbstructCar(Car car)
{
this.car = car;
}
public override void Print()
{
if (this.car != null)
{
this.car.Print();
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 设计模式练习.Model.装饰者模式
{
//奥迪车:装修者模式中的具体组件类
public class ADCar : Car
{
public string Result { get; set; }
//重写基类方法
public override void Print()
{
Result = "开始执行具体的对象-奥迪汽车";
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 设计模式练习.Model.装饰者模式
{
public class BigLight : AbstructCar
{
public BigLight(Car car) : base(car)
{
}
public override void Print()
{
base.Print();
//添加新的行为
addBigLight();
}
private void addBigLight()
{
Result = "现在奥迪车加装了炫酷的大灯了。。。";
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 设计模式练习.Model.装饰者模式
{
//汽车抽象类:装饰者模式中的抽象组件类
public abstract class Car
{
public abstract void Print();
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 设计模式练习.Model.装饰者模式
{
internal class Navigation : AbstructCar
{
public Navigation(Car car) : base(car)
{
}
public override void Print()
{
base.Print();
//增加新的行为
addNav();
}
private void addNav()
{
Result = "奥迪车新增了一个导航,太牛了";
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 设计模式练习.Model.装饰者模式
{
//汽车贴膜:具体装饰者
public class Sticker : AbstructCar
{
public Sticker(Car car) : base(car)
{
}
public override void Print()
{
base.Print();
//添加新的行为
addSticker();
}
private void addSticker()
{
Result = "奥迪车已经贴膜了";
}
}
}
二 View
<Window x:Class="设计模式练习.View.装饰者模式.Decorators"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:设计模式练习.View.装饰者模式"
mc:Ignorable="d"
Title="Decorators" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="{Binding Res1}"/>
<Label Grid.Row="1" Grid.Column="0" Content="{Binding Res2}"/>
<Label Grid.Row="2" Grid.Column="0" Content="{Binding Res3}"/>
<Button Grid.Row="0" Grid.Column="1" Content="增加大灯" Command="{Binding add1Command}"/>
<Button Grid.Row="1" Grid.Column="1" Content="增加贴膜" Command="{Binding add2Command}"/>
<Button Grid.Row="2" Grid.Column="1" Content="增加全球导航" Command="{Binding add3Command}"/>
</Grid>
</Window>
三 ViewModel
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using 设计模式练习.Model.装饰者模式;
namespace 设计模式练习.ViewModel.装饰者模式
{
partial class Combination_ViewModel : ObservableObject
{
//购买了一款奥迪车
Car car=new ADCar();
[ObservableProperty]
private string res1;
[ObservableProperty]
private string res2;
[ObservableProperty]
private string res3;
[RelayCommand]
private void add2()
{
//汽车加装贴膜
AbstructCar abstructCar = new Sticker(car);
//正式加装贴膜
abstructCar.Print();
Res1 = abstructCar.Result;
}
[RelayCommand]
private void add1()
{
//汽车加装大灯
AbstructCar abstructCar = new BigLight(car);
//正式加装大灯
abstructCar.Print();
Res2 = abstructCar.Result;
}
[RelayCommand]
private void add3()
{
//汽车加装导航
AbstructCar abstructCar = new Navigation(car);
//正式加装导航
abstructCar.Print();
Res3 = abstructCar.Result;
}
}
}