当我们需要在不改变原有类的情况下对其进行新功能添加或修改时,装饰模式是一种适用的设计模式。它允许向一个现有对象添加新的功能,同时又不改变其结构。该模式是一种结构性模式。
装饰模式(Decorator)的基本结构
装饰模式有四个角色:
- 抽象构建(Component):定义一个对象接口,可以给这些对象动态地添加职责。
- 具体构建(ConcreteComponent):定义一个具体对象,实现抽象构建接口。
- 装饰(Decorator):持有一个构件对象的实例,并定义一个与抽象构件接口一致的接口。
- 具体装饰(ConcreteDecorator):向组件添加新的职责。
以大杯奶茶为例的装饰模式
下面我们来使用大杯奶茶为例进行装饰,这里我们定义一个抽象构建 - 饮料(Beverage),它有一个计算价格的方法。
public abstract class Beverage
{
public abstract double Cost();
}
而具体构建是在抽象构建之上实现的,下面我们定义一种具体构建 - 大杯奶茶(LargeMilkTea),它通过继承饮料来实现其自身的功能:
public class LargeMilkTea : Beverage
{
public override double Cost()
{
return 10.0;
}
}
现在,如果我们需要给大杯奶茶添加一份珍珠的话,可以使用装饰模式来实现,我们定义一个装饰 - 珍珠(Pearl),它持有一个饮料对象,并且也实现了计算价格的方法,但是它还增加了一份珍珠的花费:
public class Pearl : Beverage
{
public Beverage Beverage { get; set; }
public Pearl(Beverage beverage)
{
Beverage = beverage;
}
public override double Cost()
{
return Beverage.Cost() + 3.0;
}
}
最后,我们可以使用以下代码创建一个大杯奶茶并加上一份珍珠:
Beverage milkTea = new LargeMilkTea();
milkTea = new Pearl(milkTea);
Console.WriteLine("花费:" + milkTea.Cost().ToString());
以数字为例子的装饰模式
下面,我们再以数字为例进行一个装饰,我们定义一个抽象构建 - 数字(Number),它有一个获取数字值的方法。
public abstract class Number
{
public abstract int GetValue();
}
而具体构建是在抽象构建之上实现的,下面我们定义一种具体构建 - 十进制数(DecimalNumber),它实现了数字的功能:
public class DecimalNumber : Number
{
private int value;
public DecimalNumber(int value)
{
this.value = value;
}
public override int GetValue()
{
return value;
}
}
现在我们定义一个装饰 - 减一(MinusOne),它持有一个数字对象,并且也实现了获取数字值的方法,但是它返回的值减一:
public class MinusOne : Number
{
public Number Number { get; set; }
public MinusOne(Number number)
{
Number = number;
}
public override int GetValue()
{
return Number.GetValue() - 1;
}
}
最后,我们可以使用以下代码创建一个数字对象并减一:
Number number = new DecimalNumber(10);
number = new MinusOne(number);
Console.WriteLine("值:" + number.GetValue().ToString());
以上两个例子均为装饰模式的经典示例,它们展示了装饰模式能如何在已有对象中添加新功能而不改变其结构。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:.net设计模式之装饰模式(Decorator) - Python技术站