C#装饰器-接口还是抽象类?
这个线程有一个使用抽象类的装饰器实现。我不喜欢这个简单的事实,即调味品装饰师在这里给出的实现中不是饮料。我会使用接口。抽象类对于is-a关系不是更好,接口对于has-a关系不是更好吗C#装饰器-接口还是抽象类?,c#,decorator,C#,Decorator,这个线程有一个使用抽象类的装饰器实现。我不喜欢这个简单的事实,即调味品装饰师在这里给出的实现中不是饮料。我会使用接口。抽象类对于is-a关系不是更好,接口对于has-a关系不是更好吗 public interface IBeverage { // get a description of the beverage String Description { get; } // calculate cost of the beverage double Cost {
public interface IBeverage
{
// get a description of the beverage
String Description { get; }
// calculate cost of the beverage
double Cost { get; }
}
// HouseBlend coffee implements IBeverage
public class HouseBlend : IBeverage
{
private string description;
public String Description
{
get { return description; }
}
private double cost;
public double Cost
{
get { return cost; }
}
// Constructor
public HouseBlend() { description = "House Blend"; cost = 0.89; }
}
// DarkRoast coffee implements IBeverage
public class DarkRoast : IBeverage
{
private string description;
public String Description
{
get { return description; }
}
private double cost;
public double Cost
{
get { return cost; }
}
// Constructor
public DarkRoast() { description = "Dark Roast"; cost = 1.10; }
}
// Mocha is a Decorator
public class Mocha
{
// Mocha has-a Beverage
private IBeverage m_beverage;
private string description;
public String Description
{
get { return description; }
}
private public double Cost
{
get { return cost; }
}
// Constructor binds the object passed to member var
public Mocha(IBeverage beverage)
{
m_beverage = beverage; // not necessary for the purpose of this example
description = m_beverage.Description + ", Mocha";
cost = 0.20 + m_beverage.Cost;
}
}
Use like this:
Mocha mhb = new Mocha(new HouseBlend()); // house blend with mocha flavor
基类和接口都经常用于为is-a关系建模。即使像
IDisposable
这样简单的界面也可以理解为“是一个具有手动控制生命周期的对象”,一个“一次性的”。更明显的区别在于是否允许基本实现或数据字段;以及它们组合多个层次结构的能力
现在,当您实现任何模式时,您通常有足够的信息来查看是否需要数据字段。然而,随着软件的发展,您很难排除将来需要在其他模式中包含相同的类。从这个角度来看,与抽象类相比,接口的一般偏好为您提供了更长期的灵活性——只要您有选择
作为一个装饰师,你有一个选择。组件通常没有预定义的嵌套顺序。如果有,您将直接使用继承,而不是组件。因此,您应该更喜欢使用接口来组成装饰器
尽管如此,你最初的论点也是有效的。如果您愿意,装饰器组件(特性)可以理解为is-a关系;但这不是最自然的看待方式。这可能更适合程序员。stackexchange.com我完全同意,但这不是你所指问题的重点。是的,在不是is-a关系的东西上烧掉你唯一的基类是个坏主意。我想当你想把
Mocha
对象传递给想要IBeverage
的东西时,问题就来了。怎么做?我想你真的需要一个Mocha
类来实现IBeverage
,并使用MochaDecorator
来帮助实现。如果你为描述和成本添加一个MochaDecorator,并在实现IBeverage的Mocha类中使用它,你就不需要在Mocha类中使用描述和成本。但它们必须由IBeverage实现!不行。也许只是“调味品装饰师”这个名字让我困惑。BeverageDecorator怎么样?它给你一种新型饮料,但它仍然是一种饮料。所以摩卡确实会实施IBeverage。但在这种情况下,我根本不需要额外的BeverageDecorator类。摩卡咖啡现在被称为摩卡咖啡机,我已经喝完了。