Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 你能移除一个装饰器吗?_C#_Design Patterns_Oop_Decorator - Fatal编程技术网

C# 你能移除一个装饰器吗?

C# 你能移除一个装饰器吗?,c#,design-patterns,oop,decorator,C#,Design Patterns,Oop,Decorator,是否可以从对象中删除装饰器 假设我有以下代码: abstract class Item { decimal cost(); } class Coffee : Item { decimal cost() { // some stuff } } abstract class CoffeeDecorator : Item { Item decoratedItem; } class Mocha : CoffeeDecorator { Item decora

是否可以从对象中删除装饰器

假设我有以下代码:

abstract class Item
{
    decimal cost();
}

class Coffee : Item
{
    decimal cost()
    { // some stuff }
}

abstract class CoffeeDecorator : Item
{
    Item decoratedItem;
}

class Mocha : CoffeeDecorator 
{
    Item decoratedItem;

    public Mocha(Coffee coffee)
    {
       decoratedItem = coffee;
    }
}

public void Main(string[] args)
{
    Item coffeeDrink = new Mocha(new Coffee());
}
有没有办法从我的新“咖啡”对象中删除“新摩卡()”


编辑:澄清-我希望能够删除一个装饰,而不是全部。因此,如果我在咖啡对象上有一个摩卡装饰器和一个糖装饰器,我想知道我是否可以只移除“摩卡”装饰器

首先,此分配不合法:

Coffee coffee = new Mocha(new Coffee());
Mocha
不是
Coffee
,也不存在从
Mocha
Coffee
的隐式转换。要“删除”装饰器,您需要提供一个方法或一个强制转换。因此,您可以向
Mocha
添加一个不装饰的方法:

public Coffee Undecorate() {
    return (Coffee)decoratedItem;
}
那么你可以说

Coffee coffee = new Mocha(new Coffee()).Undecorate();
或者,您可以在
Mocha
类中提供隐式cast操作符:

public static implicit operator Coffee(Mocha m) {
    return (Coffee)m.decoratedItem;
}
那你的台词呢

Coffee coffee = new Mocha(new Coffee());
这是合法的

现在,您的问题暗示了对设计模式的潜在误解(事实上,您的实现也暗示了这种误解)。你想做的事很难闻。使用decorator模式的正确方法如下。请注意,
CoffeeDecorator
源于
Coffee

abstract class Item { public abstract decimal Cost(); }
class Coffee : Item { public override decimal Cost() { return 1.99m; } }
abstract class CoffeeDecorator : Coffee {
    protected Coffee _coffee;
    public CoffeeDecorator(Coffee coffee) { this._coffee = coffee; }
}
class Mocha : CoffeeDecorator {
    public Mocha(Coffee coffee) : base(coffee) { }
    public override decimal Cost() { return _coffee.Cost() + 2.79m; }
}
class CoffeeWithSugar : CoffeeDecorator {
    public CoffeeWithSugar(Coffee coffee) : base(coffee) { }
    public override decimal Cost() { return _coffee.Cost() + 0.50m; }
}
然后你可以说:

Coffee coffee = new Mocha(new CoffeeWithSugar(new Coffee()));
Console.WriteLine(coffee.Cost()); // output: 5.28

有鉴于此,您需要取消装饰它做什么?

首先,此分配不合法:

Coffee coffee = new Mocha(new Coffee());
Mocha
不是
Coffee
,也不存在从
Mocha
Coffee
的隐式转换。要“删除”装饰器,您需要提供一个方法或一个强制转换。因此,您可以向
Mocha
添加一个不装饰的方法:

public Coffee Undecorate() {
    return (Coffee)decoratedItem;
}
那么你可以说

Coffee coffee = new Mocha(new Coffee()).Undecorate();
或者,您可以在
Mocha
类中提供隐式cast操作符:

public static implicit operator Coffee(Mocha m) {
    return (Coffee)m.decoratedItem;
}
那你的台词呢

Coffee coffee = new Mocha(new Coffee());
这是合法的

现在,您的问题暗示了对设计模式的潜在误解(事实上,您的实现也暗示了这种误解)。你想做的事很难闻。使用decorator模式的正确方法如下。请注意,
CoffeeDecorator
源于
Coffee

abstract class Item { public abstract decimal Cost(); }
class Coffee : Item { public override decimal Cost() { return 1.99m; } }
abstract class CoffeeDecorator : Coffee {
    protected Coffee _coffee;
    public CoffeeDecorator(Coffee coffee) { this._coffee = coffee; }
}
class Mocha : CoffeeDecorator {
    public Mocha(Coffee coffee) : base(coffee) { }
    public override decimal Cost() { return _coffee.Cost() + 2.79m; }
}
class CoffeeWithSugar : CoffeeDecorator {
    public CoffeeWithSugar(Coffee coffee) : base(coffee) { }
    public override decimal Cost() { return _coffee.Cost() + 0.50m; }
}
然后你可以说:

Coffee coffee = new Mocha(new CoffeeWithSugar(new Coffee()));
Console.WriteLine(coffee.Cost()); // output: 5.28

有鉴于此,您需要为其取消装饰什么?

如果您能更灵活地编写代码,您可以

若要移除一个装饰器,请将它们全部拆开,然后重新组装,不要遗漏一个装饰器。要取消感觉,您需要能够引用每一个。添加表示包装装饰的属性,最里面的装饰将表示null

interface IDecoratedExpressing {
    IDecoratedExpressing InnerDecorated {get;}
}
然后


也可以将
InnerDecorated
属性设置为可设置的,这样您就可以以不同的方式将它们重新组合在一起(或者保留一个或多个)。这意味着您可以通过setter属性而不是仅在构造时操纵装饰。允许灵活性。不确定这有多洁净。只是在思考

如果编码更灵活,您可以

若要移除一个装饰器,请将它们全部拆开,然后重新组装,不要遗漏一个装饰器。要取消感觉,您需要能够引用每一个。添加表示包装装饰的属性,最里面的装饰将表示null

interface IDecoratedExpressing {
    IDecoratedExpressing InnerDecorated {get;}
}
然后


也可以将
InnerDecorated
属性设置为可设置的,这样您就可以以不同的方式将它们重新组合在一起(或者保留一个或多个)。这意味着您可以通过setter属性而不是仅在构造时操纵装饰。允许灵活性。不确定这有多洁净。只是在思考

使用对子项和父项的引用有时可能会让人不知所措

另一种方法是实现一个抽象的decorator类,其中一个布尔状态将告诉您decorator是“开”还是“关”。使用抽象类将允许您将remove decorator的所有逻辑放在一个位置,然后可以在此基础上构建所有具体的decorator,而无需担心remove

您将有一个remove decorator方法,该方法设置为true此变量如果这是要删除的decorator,则与decorator在装饰链中的位置无关:

public void RemoveDecorator(DECORATOR_CODES decCode)
{
            if (this.Code == decCode)
            {
                bDecoratorRemoved = true;
            }
            else
                this.ParentBevarage.RemoveDecorator(decCode);
        }


 public float Cost()
        {
            if (!bDecoratorRemoved)
                return this.ParentBevarage.Cost() + this.Price;
            else
                return this.ParentBevarage.Cost();
        }

你并不是真的移除了decorator,而是中和了它的效果,这在内存方面不是更有效的,但肯定会允许你移除任何decorator,你想要多少,只需要几行代码。如果物品对象不太多,而且寿命很短,那么它可能是有价值的。

使用对子物品和父物品的引用有时会让人不知所措

另一种方法是实现一个抽象的decorator类,其中一个布尔状态将告诉您decorator是“开”还是“关”。使用抽象类将允许您将remove decorator的所有逻辑放在一个位置,然后可以在此基础上构建所有具体的decorator,而无需担心remove

您将有一个remove decorator方法,该方法设置为true此变量如果这是要删除的decorator,则与decorator在装饰链中的位置无关:

public void RemoveDecorator(DECORATOR_CODES decCode)
{
            if (this.Code == decCode)
            {
                bDecoratorRemoved = true;
            }
            else
                this.ParentBevarage.RemoveDecorator(decCode);
        }


 public float Cost()
        {
            if (!bDecoratorRemoved)
                return this.ParentBevarage.Cost() + this.Price;
            else
                return this.ParentBevarage.Cost();
        }

你并不是真的移除了decorator,而是中和了它的效果,这在内存方面不是更有效的,但肯定会允许你移除任何decorator,你想要多少,只需要几行代码。如果物品对象不太多,而且寿命很短,那么它是值得的。

为了进一步阐明John K.所说的,装饰图案可以被认为是一个链表,在这个链表上添加一个setter是很自然的


要删除层,只需将其父链接的引用指向其子链接即可;或者,在Decorator模式术语中,要删除Decorator foo,请将foo的Decorator的装饰对象引用指向foo的装饰对象。

要建立并澄清John K.所说的内容,可以将Decorator模式视为一个链表,在该链表中添加setter是o