我正在学习更多关于设计模式的知识,我正在尝试实现装饰器模式。我想扩展一个计算机对象,在每个新组件的描述末尾添加一个字符串。这是 Unity/C# 改编自《傻瓜设计模式》一书中的 Java 示例。
public class Computer {
public Computer(){}
public string Description(){
return "Computer";
}
}
这是每个组件将继承自的装饰器组件:
public abstract class ComponentDecorator : Computer {
new public abstract string Description();
}
下面是两个组件类监视器和磁盘,它们可以装饰计算机类。
public class Monitor : ComponentDecorator {
Computer computer;
public Monitor(Computer c){
this.computer = c;
}
public override string Description(){
return computer.Description () + " and a Monitor";
}
}
public class Disk : ComponentDecorator {
Computer computer;
public Disk(Computer c){
this.computer = c;
}
public override string Description(){
return computer.Description () + " and a Disk";
}
}
下面是启动方法:
void Start(){
Computer computer = new Computer ();
computer = new Disk (computer);
computer = new Monitor (computer);
print("You have a " + computer.Description () + ".");
}
我的预期输出是:"你有一台计算机、一台显示器和一个磁盘。
实际输出为:"你有一台计算机。
计算机现在不应该像调用监视器描述方法一样调用描述方法吗?如何修改它以获得预期的输出?
您可以通过使要修饰的类和装饰器类具有相同的抽象(接口或抽象类(来实现装饰器。下面的代码演示如何使用抽象类。我在此处添加的 Device 类是装饰器类和装饰类的抽象。
public abstract class Device
{
public abstract string Description();
}
public class Computer : Device
{
public Computer() { }
public override string Description()
{
return "Computer";
}
}
public class Monitor : Device
{
Device device;
public Monitor(Device c)
{ this.device = c;
}
public override string Description()
{
return device.Description() + " and a Monitor";
}
}
public class Disk : Device
{
Device device;
public Disk(Device c)
{
this.device = c;
}
public override string Description()
{
return device.Description() + " and a Disk";
}
}
你不需要装饰器类的抽象,除非你希望所有的装饰器实现任何特定的方法。
你的暗示有缺失的点。 http://www.dofactory.com/net/decorator-design-pattern 有同样好的解释和UML图。我像这样实现你的案例:
public abstract class ComputerParts
{
public abstract string Description();
}
public class Computer : ComputerParts
{
public Computer()
{
}
public override string Description()
{
return "Computer";
}
}
public abstract class ComponentDecorator : ComputerParts
{
public abstract void ExtraMethod();
}
public class Disk : ComponentDecorator
{
ComputerParts computerParts;
public Disk(ComputerParts c)
{
this.computerParts = c;
}
public override string Description()
{
return computerParts.Description() + " and a Disk";
}
public override void ExtraMethod()
{
throw new NotImplementedException();
}
}
public class Monitor : ComponentDecorator
{
ComputerParts computerParts;
public Monitor(ComputerParts c)
{
this.computerParts = c;
}
public override string Description()
{
return computerParts.Description() + " and a Monitor";
}
public override void ExtraMethod()
{
throw new NotImplementedException();
}
}