【问题标题】:How to remove decorators out of order in C#如何在 C# 中乱序删除装饰器
【发布时间】:2011-10-07 02:07:01
【问题描述】:
我正在尝试实现一个简单的应用程序,让我可以在汽车中选择附加功能。
每个额外的项目都是基类 Car 的装饰器。
假设我做了以下事情
Car p = new FordFusion();
p = new ElectricWindows(p);
p = new LeatherSeatings(p);
p = new Airbags(p);
那么我的对象 p 将是一辆带有电动车窗、真皮座椅和安全气囊的福特 Fusion。
我需要让用户无序地移除装饰器,例如,在不移除皮革座椅和安全气囊的情况下移除电动车窗
【问题讨论】:
标签:
c#
design-patterns
decorator
【解决方案1】:
听起来像装饰器模式可能不是为您的域建模的最佳方式。你的装饰师真的需要改变汽车的行为吗?还是它们只是增加了成本/价格?
您是否尝试过将 ICarFeatures 集合作为 Car 类的成员? ICarFeature 可以有一个 GetCost 方法或类似的方法来允许将汽车的总成本相加。
【解决方案2】:
我可能会用Chain of responsibility 解决这个问题。我会创建一个处理程序接口
public interface IAccessoryHandler
{
bool CanHandle( UserOption option ); // UserOption is an enum of Electric Window etc.
Handle( Car car );
}
然后我会创建处理程序实现,即 ElectricWindowHandler、LeatherHandler 等,例如 CanHandle() => if option == UserOption.electric then Handle() => car.Accessories.Add(new ElectricWindow);
每次用户更改选项时,我都会清除汽车配件集合,对选定的用户选项执行一次 foreach 并让汽车对象在链中运行。在链条过程结束时,您的汽车将拥有正确的配件。
【解决方案3】:
可能有一个集中的对象,它告诉您哪个模型已弃用哪些功能,因此您不必完全更改每个装饰器模式。只是对其中的一个小修改,我的意思是在 ElectricWindows 返回 Car 对象之前,它会检查它是否有资格拥有此功能。
希望我说得通!
【解决方案4】:
我的回答假设您不会放弃装饰器方法。
在您的问题中,您规定可以无序删除 Decorators,这基本上使 kibosh 推荐使用 Undo/Redo 或 Decorate/UnDecorate 方法。
我认为您可能会利用Memento 模式。跟踪Car 的状态以及应用了哪些Decorators。通过删除装饰器,您基本上遍历应用的装饰器堆栈直到所需的状态并将Car 对象恢复到该状态(之前应用删除的装饰器)。然后,您将需要重新应用随后进行的装饰器。可能不是最佳解决方案,但对您当前的设计影响最小。