【问题标题】:Implementing clone() with the decorator pattern使用装饰器模式实现 clone()
【发布时间】:2010-12-21 19:20:09
【问题描述】:

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

在这个装饰器场景中:

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

然后(遵循装饰器模式)它将clone() 委托回原始mario 实例。所以clone() 会返回原来的mario 而不是升级后的版本。

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

有什么建议吗?

【问题讨论】:

    标签: prototype design-patterns clone decorator


    【解决方案1】:

    装饰器添加了功能,因此您不必将所有内容都委托给原始 mario。

    是的,您可以将克隆委托给原始 mario,但您的装饰器随后将使用自己更大的胡子更新 mustache 属性,然后返回更新后的克隆;

    更新解释克隆: 装饰器模式的重点是隐藏被包装对象的新功能,因此被包装对象不会克隆被装饰的属性。您调用顶级装饰器的 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;
            }
    

    装饰器使用原始对象的克隆方法,然后更新它自己改变的属性。但它仍然是负责最终结果的装饰器。

    【讨论】:

    • 呵呵,最近写了很多 C# 代码,所以我用 ; 结束了我的句子。代替 。 =)
    • 但是原始 mario 上的 clone() 是如何访问修饰属性的呢?
    • @johnlindquist 更新了我的答案以解释
    猜你喜欢
    • 2012-02-16
    • 2020-02-29
    • 2018-12-23
    • 2015-05-27
    • 2011-03-08
    • 2019-03-25
    • 2018-06-28
    • 1970-01-01
    • 2018-03-10
    相关资源
    最近更新 更多