Шаблон проектирования Декоратор без конкретных объектов
От: zfima  
Дата: 02.09.12 18:52
Оценка:
Здравствуйте.
В примерах существует конкретный объект, который декорируем. Использую стандартную имплементацию банды 4-х.
Например кофе обворачиваем в 3 сахара и обворачиваем в 1 молоко и распечатываем ингридиенты и цену —

ICofeeProduct prod2 = new Sugar(new Sugar(new Sugar(new Milk(new DarkRoast()))));
Console.WriteLine("I am {0}, my cost is {1}", prod2.Name(), prod2.Cost());


DarkRoast — конкретный объект, остальное — декорация.

Но, по-моему возникают 2 проблемы:
1. Надо помнить, кто конкретный объект, а кто декорация
т.е так:
ICofeeProduct prod2 = new Sugar(new Sugar(new DarkRoast(new Milk(new Sugar()))));

работать не будет, хотя по-моему смысл не поменялся: 3 сахара + 1 молоко + 1 кофе

2. Невозможно сделать 2 DarkRoast (типа, сильный кофе)
т.е так:
ICofeeProduct prod2 = new Sugar(new Sugar(new Sugar(new DarkRoast(new DarkRoast()))));

работать не будет

Я подумал о следующей реализации шаблона (Null object шаблон мне подсказали):

public interface ICofeeProduct
{
    double Cost();
    string Name();
}

public class Empty : ICofeeProduct
{
    public double Cost() { return 0.0; }
    public string Name() { return ""; }
}

public class DarkRoast : ICofeeProduct
{
    ICofeeProduct _product;

    public DarkRoast(ICofeeProduct prod = null)
    {
        _product = (prod == null) ? new Empty() : prod;
    }

    public double Cost() { return 2.5 + _product.Cost(); }
    public string Name() { return "DarkRoast " + _product.Name(); }
}

public class Milk : ICofeeProduct
{
    ICofeeProduct _product;

    public Milk(ICofeeProduct prod = null)
    {
        _product = (prod == null) ? new Empty() : prod;
    }

    public double Cost() { return 0.5 + _product.Cost(); }
    public string Name() { return "With milk " + _product.Name(); }
}

public class Sugar : ICofeeProduct
{
    ICofeeProduct _product;

    public Sugar(ICofeeProduct prod = null)
    {
        _product = (prod == null) ? new Empty() : prod;
    }

    public double Cost() { return 0.2 + _product.Cost(); }
    public string Name() { return "With sugar " + _product.Name(); }
}


Я по-своему решил мои проблемы, и теперь так:

ICofeeProduct prod1 = new Sugar(new Sugar(new DarkRoast(new Milk(new Sugar()))));
ICofeeProduct prod2 = new Sugar(new Sugar(new Sugar(new DarkRoast(new DarkRoast()))));


работает.
Какие минусы есть у такой имплементации декоратора?
Спасибо
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.