Реализация clone () с шаблоном декоратора - PullRequest
0 голосов
/ 21 декабря 2010

Каков наилучший способ реализации метода clone () с использованием шаблона декоратора?

В этом сценарии декоратора:

var mario:Hero = new Mario();<br> mario = new HeroUpgrade(mario); //bigger moustache ;)<br> mario.clone(); //<--trying to grab a clone of the upgraded mario

затем (следуя шаблону Decorator) он делегирует clone() обратно в исходный экземпляр mario. Поэтому clone() вернет исходную mario, а не обновленную версию.

Я понимаю, что вместо клонирования я мог бы извлечь сувенир из обновленного экземпляра mario и вставить его в новый экземпляр Mario, но кажется, что должно быть простое решение ...

Какие-нибудь советы?

1 Ответ

0 голосов
/ 22 декабря 2010

Декоратор добавляет функциональность, поэтому вы не делегируете все обратно оригинальному mario.

Да, вы можете делегировать клон исходному mario, но ваш декоратор затем обновит свойство усов своими собственными большими усами, а затем вернет обновленный клон;

ОБНОВЛЕНО, чтобы объяснить клонирование: Весь смысл шаблона декоратора состоит в том, чтобы скрыть новую функциональность от обернутого объекта, чтобы обернутый объект не клонировал декорированные свойства. Вы вызываете метод клонирования декоратора верхнего уровня. Декоратор переопределяет метод Clone для прозрачного добавления его собственных функций.

    public class Mario : ICloneable
    {
        public Mario()
        {
            MoustacheSize = 1;
        }

        private double _moustacheSize;
        public virtual double MoustacheSize
        {
            get { return _moustacheSize; }
            internal set { _moustacheSize = value; }
        }

        public virtual object Clone()
        {
            var clone = new Mario();
            clone.MoustacheSize = this.MoustacheSize;
            return clone;
        }
    }

    public class HeroUpgradeDecorator : Mario
    {
        public HeroUpgradeDecorator(Mario mario)
        {
            _inner = mario;
        }

        private Mario _inner;

        public override double MoustacheSize
        {
            get
            {
                return _inner.MoustacheSize * 1.2; // 20% increase in moustache size
            }
        }

        public override object Clone()
        {
            var clone = new Mario();
            clone.MoustacheSize = this.MoustacheSize;
            return clone;
        }
    }

    static void Main(string[] args)
    {
        var mario = new Mario();
        Console.WriteLine("Mario, with moustache size: {0}", mario.MoustacheSize);

        Console.WriteLine("Upgrading...");
        mario = new HeroUpgradeDecorator(mario); // variable mario now points to the decorator
        Console.WriteLine("Mario, with moustache size: {0}", mario.MoustacheSize);

        Console.WriteLine("Upgrading again...");
        mario = new HeroUpgradeDecorator(mario); // variable mario now points to the 2nd decorator
        Console.WriteLine("Mario, with moustache size: {0}", mario.MoustacheSize);

        Console.ReadLine();
    }

вывод этого консольного приложения:

Mario, with moustache size: 1
Upgrading...
Mario, with moustache size: 1.2
Upgrading again...
Mario, with moustache size: 1.44

В качестве альтернативы, если существует множество свойств для клонирования, декоратор может сделать это:

        public override object Clone()
        {
            var clone = (Mario)_inner.Clone();
            clone.MoustacheSize = this.MoustacheSize;
            return clone;
        }

Декоратор использует метод clone исходного объекта, а затем обновляет свойства, которые он сам меняет. Но за конечный результат отвечает декоратор.

...