使用装饰器模式实现clone()

时间:2010-12-21 19:20:10

标签: prototype design-patterns clone decorator

使用装饰器模式实现clone()方法的最佳方法是什么?

在这个装饰者场景中:

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

然后(在Decorator模式之后)它会将clone()委托回原来的mario实例。因此clone()将返回原始mario而非升级版本。

我意识到,不是克隆,我可以从升级的马里奥实例中获取纪念品并将其注入新的Mario实例,但感觉应该有一个更简单的解决方案......

任何提示?

1 个答案:

答案 0 :(得分:0)

装饰器添加了功能,因此您不会将所有内容委托回原始马里奥。

是的,您可以将克隆委托给原始马里奥,但您的装饰者将使用它自己更大的胡子更新胡须属性,然后返回更新的克隆;

更新解释克隆: 装饰器模式的重点是从包装对象中隐藏新功能,因此包装对象不会克隆装饰属性。您调用顶级装饰器的clone方法。装饰器会覆盖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方法,然后更新它自己更改的属性。但它仍然是负责最终结果的装饰者。