2010-12-21 93 views
0

使用装饰器模式实现clone()方法的最佳方式是什么?使用装饰器模式实现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而不是升级版本。

我意识到这一点,而不是克隆,我可以抓住纪念关升级马里奥实例,并注入到这一点马里奥的新实例,但感觉应该有一个简单的解决方案...

有小费吗?

回答

0

装饰者增加了功能,所以你不会将所有事情都委托给原始的马里奥。

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

更新来解释克隆: 装饰模式的全部要点是隐藏包装对象的新功能,所以包装的对象不克隆装饰的属性。您调用顶级装饰器的克隆方法。装饰器重写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; 
     } 

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

+0

呵呵,最近我一直在做这么多的C#代码,我终于结束了我的判决;代替 。 =) – Stefan 2010-12-22 00:49:13