在装饰模式中添加状态

发布于 2024-12-14 12:24:50 字数 1083 浏览 3 评论 0原文

我想知道如何向消费者可用的装饰器链添加状态。给定这个简化的模型:

abstract class AbstractPizza 
{
    public abstract print(...);
}

class Pizza : AbstractPizza 
{
    public int Size { get; set; }
    public print(...);
}

abstract class AbstractPizzaDecorator 
{
    public Pizza:AbstractPizza;
    public abstract print();
}

class HotPizzaDecorator : AbstractPizzaDecorator 
{
    public int Hotness { get; set; }
    public print(...);
}

class CheesyPizzaDecorator : AbstractPizzaDecorator 
{
    public string Cheese { get; set; }
    public print(...);
}


void Main()
{
    BigPizza = new Pizza();
    BigPizza.Size = 36;

    HotBigPizza = new HotPizzaDecorator();
    HotBigPizza.Pizza = BigPizza;
    HotBigPizza.Hotness = 3;

    HotBigCheesyPizza = new CheesyPizzaDecorator();
    HotBigCheesyPizza.Pizza = HotBigPizza;
    HotBigCheesyPizza.Cheese = "Blue";

    HotBigCheesyPizza.print();
    HotBigCheesyPizza.size = 28; // ERRRRRR !
}

现在,如果它们都实现 print 方法并通过链传播该方法,那么一切都很好。但这对国家来说如何运作呢?我无法访问 HotBigCheesyPizza 上的大小属性。

我缺少什么部分?图案错误?

感谢您的帮助! 干杯

I wonder how to add state to the chain of decorators that will be available to the consumer. Given this simplified model:

abstract class AbstractPizza 
{
    public abstract print(...);
}

class Pizza : AbstractPizza 
{
    public int Size { get; set; }
    public print(...);
}

abstract class AbstractPizzaDecorator 
{
    public Pizza:AbstractPizza;
    public abstract print();
}

class HotPizzaDecorator : AbstractPizzaDecorator 
{
    public int Hotness { get; set; }
    public print(...);
}

class CheesyPizzaDecorator : AbstractPizzaDecorator 
{
    public string Cheese { get; set; }
    public print(...);
}


void Main()
{
    BigPizza = new Pizza();
    BigPizza.Size = 36;

    HotBigPizza = new HotPizzaDecorator();
    HotBigPizza.Pizza = BigPizza;
    HotBigPizza.Hotness = 3;

    HotBigCheesyPizza = new CheesyPizzaDecorator();
    HotBigCheesyPizza.Pizza = HotBigPizza;
    HotBigCheesyPizza.Cheese = "Blue";

    HotBigCheesyPizza.print();
    HotBigCheesyPizza.size = 28; // ERRRRRR !
}

Now if they all implement the print method and propagate that though the chain, it's all good. But how does that work for the state? I can't access the size property on the HotBigCheesyPizza.

What's the part that I'm missing? Wrong pattern?

Thanks for helping!
Cheers

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

鹿港小镇 2024-12-21 12:24:50

装饰器模式用于向被装饰类添加额外的行为,而无需客户端进行调整。因此,它并不是为了向被装饰的事物添加新的界面(例如hotnesscheese)。

一个不太好的例子是,您想要更改 size 的计算方式:您可以创建一个 MetricSizePizzaDecorator 来将尺寸转换为英语/英语/公制单位。客户端不会知道披萨已被装饰 - 它只是调用 getSize() 并对结果执行任何需要执行的操作(例如,计算价格)。

我可能不会在我的示例中使用装饰器,但要点是:它不会改变界面。事实上,几乎所有的设计模式都可以归结为这一点——在不改变界面的情况下增加设计的可变性。

The decorator pattern is for adding additional behavior to the decorated class without the client needing to adjust. Thus it is not intended for adding a new interface (e.g. hotness, cheese) to the thing being decorated.

A somewhat bad example of what it might be used for is where you want to change how size is calculated: you could create a MetricSizePizzaDecorator that converts the size to/from English/metric units. The client would not know the pizza has been decorated - it just calls getSize() and does whatever it needs to do with the result (for example, to calculate the price).

I would probably not use the decorator in my example, but the point is: it does not alter the interface. In fact, nearly all design patterns come down to that - adding variability to a design without changing interfaces.

星星的軌跡 2024-12-21 12:24:50

添加状态的一种方法是使用自引用数据结构(列表)。但这使用了访问者模式,并且做的事情比您可能想要的更多。此代码重写自一点 Java,一些模式

// a self referential data structure with different types of nodes
abstract class Pie
    {
    abstract Object accept(PieVisitor ask);
    }
class Bottom extends Pie
    {
    Object accept(PieVisitor ask) { return ask.forBottom(this); }
    public String toString() { return "crust"; }
    }
class Topping extends Pie
    {
    Object topping;
    Pie rest;
    Topping(Object topping,Pie rest) { this.topping=topping; this.rest=rest; }
    Object accept(PieVisitor ask) { return ask.forTopping(this); }
    public String toString() { return topping+" "+rest.toString(); }
    }
//a class to manage the data structure
interface PieManager
    {
    int addTopping(Object t);
    int removeTopping(Object t);
    int substituteTopping(Object n,Object o);
    int occursTopping(Object o);
    }
class APieManager implements PieManager
    {
    Pie p=new Bottom();
    // note: any object that implements a rational version of equal() will work
    public int addTopping(Object t)
        {
        p=new Topping(t,p);
        return occursTopping(t);
        }
    public int removeTopping(Object t)
        {
        p=(Pie)p.accept(new RemoveVisitor(t));
        return occursTopping(t);
        }
    public int substituteTopping(Object n,Object o)
        {
        p=(Pie)p.accept(new SubstituteVisitor(n,o));
        return occursTopping(n);
        }
    public int occursTopping(Object o)
        {
        return ((Integer)p.accept(new OccursVisitor(o))).intValue();
        }
    public String toString() { return p.toString(); }
    }
//these are the visitors
interface PieVisitor
    {
    Object forBottom(Bottom that);
    Object forTopping(Topping that);
    }
class OccursVisitor implements PieVisitor
    {
    Object a;
    OccursVisitor(Object a) { this.a=a; }
    public Object forBottom(Bottom that) { return new Integer(0); }
    public Object forTopping(Topping that)
        {
        if(that.topping.equals(a))
            return new Integer(((Integer)(that.rest.accept(this))).intValue()+1);
            else return that.rest.accept(this);
        }
    }
class SubstituteVisitor implements PieVisitor
    {
    Object n,o;
    SubstituteVisitor(Object n,Object o) { this.n=n; this.o=o; }
    public Object forBottom(Bottom that) { return that; }
    public Object forTopping(Topping that)
        {
        if(o.equals(that.topping))
            that.topping=n;
        that.rest.accept(this);
        return that;
        }
    }
class RemoveVisitor implements PieVisitor
    {
    Object o;
    RemoveVisitor(Object o) { this.o=o; }
    public Object forBottom(Bottom that) { return new Bottom(); }
    public Object forTopping(Topping that)
        {
        if(o.equals(that.topping))
            return that.rest.accept(this);
            else return new Topping(that.topping,(Pie)that.rest.accept(this));
        }
    }
public class TestVisitor
    {
    public static void main(String[] args)
        {
        // make a PieManager
        PieManager pieManager=new APieManager();
        // add some toppings
        pieManager.addTopping(new Float(1.2));
        pieManager.addTopping(new String("cheese"));
        pieManager.addTopping(new String("onions"));
        pieManager.addTopping(new String("cheese"));
        pieManager.addTopping(new String("onions"));
        pieManager.addTopping(new String("peperoni"));
        System.out.println("pieManager="+pieManager);
        // substitute anchovies for onions
        int n=pieManager.substituteTopping(new String("anchovies"),new String("onions"));
        System.out.println(n+" pieManager="+pieManager);
        // remove the 1.2's
        n=pieManager.removeTopping(new Float(1.2));
        System.out.println(n+" pieManager="+pieManager);
        // how many anchovies do we have?
        System.out.println(pieManager.occursTopping(new String("anchovies"))+" anchovies");
        }
    }

one way of adding state is by using a self referential data structure (a list). but this uses the visitor pattern and does more than you probably want. this code is rewritten from A little Java, a few patterns

// a self referential data structure with different types of nodes
abstract class Pie
    {
    abstract Object accept(PieVisitor ask);
    }
class Bottom extends Pie
    {
    Object accept(PieVisitor ask) { return ask.forBottom(this); }
    public String toString() { return "crust"; }
    }
class Topping extends Pie
    {
    Object topping;
    Pie rest;
    Topping(Object topping,Pie rest) { this.topping=topping; this.rest=rest; }
    Object accept(PieVisitor ask) { return ask.forTopping(this); }
    public String toString() { return topping+" "+rest.toString(); }
    }
//a class to manage the data structure
interface PieManager
    {
    int addTopping(Object t);
    int removeTopping(Object t);
    int substituteTopping(Object n,Object o);
    int occursTopping(Object o);
    }
class APieManager implements PieManager
    {
    Pie p=new Bottom();
    // note: any object that implements a rational version of equal() will work
    public int addTopping(Object t)
        {
        p=new Topping(t,p);
        return occursTopping(t);
        }
    public int removeTopping(Object t)
        {
        p=(Pie)p.accept(new RemoveVisitor(t));
        return occursTopping(t);
        }
    public int substituteTopping(Object n,Object o)
        {
        p=(Pie)p.accept(new SubstituteVisitor(n,o));
        return occursTopping(n);
        }
    public int occursTopping(Object o)
        {
        return ((Integer)p.accept(new OccursVisitor(o))).intValue();
        }
    public String toString() { return p.toString(); }
    }
//these are the visitors
interface PieVisitor
    {
    Object forBottom(Bottom that);
    Object forTopping(Topping that);
    }
class OccursVisitor implements PieVisitor
    {
    Object a;
    OccursVisitor(Object a) { this.a=a; }
    public Object forBottom(Bottom that) { return new Integer(0); }
    public Object forTopping(Topping that)
        {
        if(that.topping.equals(a))
            return new Integer(((Integer)(that.rest.accept(this))).intValue()+1);
            else return that.rest.accept(this);
        }
    }
class SubstituteVisitor implements PieVisitor
    {
    Object n,o;
    SubstituteVisitor(Object n,Object o) { this.n=n; this.o=o; }
    public Object forBottom(Bottom that) { return that; }
    public Object forTopping(Topping that)
        {
        if(o.equals(that.topping))
            that.topping=n;
        that.rest.accept(this);
        return that;
        }
    }
class RemoveVisitor implements PieVisitor
    {
    Object o;
    RemoveVisitor(Object o) { this.o=o; }
    public Object forBottom(Bottom that) { return new Bottom(); }
    public Object forTopping(Topping that)
        {
        if(o.equals(that.topping))
            return that.rest.accept(this);
            else return new Topping(that.topping,(Pie)that.rest.accept(this));
        }
    }
public class TestVisitor
    {
    public static void main(String[] args)
        {
        // make a PieManager
        PieManager pieManager=new APieManager();
        // add some toppings
        pieManager.addTopping(new Float(1.2));
        pieManager.addTopping(new String("cheese"));
        pieManager.addTopping(new String("onions"));
        pieManager.addTopping(new String("cheese"));
        pieManager.addTopping(new String("onions"));
        pieManager.addTopping(new String("peperoni"));
        System.out.println("pieManager="+pieManager);
        // substitute anchovies for onions
        int n=pieManager.substituteTopping(new String("anchovies"),new String("onions"));
        System.out.println(n+" pieManager="+pieManager);
        // remove the 1.2's
        n=pieManager.removeTopping(new Float(1.2));
        System.out.println(n+" pieManager="+pieManager);
        // how many anchovies do we have?
        System.out.println(pieManager.occursTopping(new String("anchovies"))+" anchovies");
        }
    }
一抹微笑 2024-12-21 12:24:50

我相信您的组件 Pizza 和抽象装饰器 PizzaDecorator 应该共享相同的接口,这样装饰器的每个实例都能够执行与核心组件相同的操作<代码>披萨。

I believe your component Pizza and your abstract decorator PizzaDecorator are supposed to share the same interface, that way each instance of the decorator is capable of the same operations as the core component Pizza.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文