首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >抽象装饰类在装饰模式中的应用

抽象装饰类在装饰模式中的应用
EN

Stack Overflow用户
提问于 2013-10-18 10:04:16
回答 1查看 865关注 0票数 6

在装饰设计模式中,我们有一个ItemClass (体育)。咖啡),然后是AbstractDecorator (体育)。CoffeeDecorator),包含对咖啡和ConcreteDecorators (如牛奶)的引用。我的问题是,为什么我们需要AbstractDecorator类,为什么具体的装饰器不直接继承咖啡类呢?或者,如果我们已经希望确保ItemClass有一个对ItemClass的引用,那么为什么我们没有一个包含ItemClass属性的接口呢?如果使用这个AbstractDecorator,我们只是禁用了ConcreteDecorators继承其他类的选项。谢谢,提前!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-10-18 10:09:06

我们使用抽象类来消除具体类中的重复。在装饰器模式中,您可以复制存储修饰对象实例并传递对它的调用。如果不将此逻辑移动到基础(抽象)装饰器,则需要在每个具体的装饰器中实现这一点。

考虑以下饮料接口:

代码语言:javascript
复制
public interface IBeverage
{
    decimal Price { get; }
    string Description { get; }
}

它是通过咖啡实现的:

代码语言:javascript
复制
public class Coffee : IBeverage
{
    public decimal Price
    {
        get { return 3.5M; }
    }

    public string Description
    {
        get { return "Coffee"; }
    }
}

现在你想要为咖啡创造第一个装饰师。您现在不需要创建抽象的装饰器。让我们的牛奶蜜蜂免费。只需编写最简单的代码即可:

代码语言:javascript
复制
public class Milk : IBeverage
{
    private readonly IBeverage _beverage;

    public Milk(IBeverage beverage)
    {
        _beverage = beverage;
    }

    public decimal Price
    {
        get { return _beverage.Price; } // price not changed
    }

    public string Description
    {
        get { return _beverage.Description + " with milk"; }
    }
}

现在你需要另一个装饰师。让它成为奶油:

代码语言:javascript
复制
public class Cream : IBeverage
{
    private readonly IBeverage _beverage;

    public Cream(IBeverage beverage)
    {
        _beverage = beverage;
    }

    public decimal Price
    {
        get { return _beverage.Price + 2M; }
    }

    public string Description
    {
        get { return _beverage.Description + " with cream"; }
    }
}

你可以看到重复的代码。现在是重构的时候了。让我们将重复代码移到抽象装饰器类的基础上,该类的责任是保持对修饰饮料的引用并传递对其的调用:

代码语言:javascript
复制
public abstract class BeverageDecorator : IBeverage
{
    private readonly IBeverage _beverage;

    public BeverageDecorator(IBeverage beverage)
    {
        _beverage = beverage;
    }

    public virtual decimal Price
    {
        get { return _beverage.Price; }
    }

    public virtual string Description
    {
        get { return _beverage.Description; }
    }
}

现在,您可以只覆盖那些被装饰者更改的调用。牛奶装潢师会看起来像:

代码语言:javascript
复制
public class Milk : BeverageDecorator
{
    public Milk(IBeverage beverage)
        : base(beverage)
    {
    }

    public override string Description
    {
        get
        {
            return base.Description + " with milk";
        }
    }
}

干净多了,对吧?所以我们才用底座装饰器。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19446913

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档