What's开发者_如何学Go the best way to implement a clone() method using the decorator pattern?
In this decorator scenario:
var mario:Hero = new Mario();
mario = new HeroUpgrade(mario); //bigger moustache ;)
mario.clone(); //<--trying to grab a clone of the upgraded mario
then (following the Decorator pattern) it would delegate the clone()
back to the original mario
instance. So clone()
would return the original mario
rather than the upgraded version.
I realize that, rather than cloning, I could grab a memento off of the upgraded mario instance and inject that into a new instance of Mario, but it feels like there should be a simpler solution...
Any tips?
A decorator adds functionality, so you don't delegate everything back to the original mario.
Yes, you can delegate clone to the original mario, but your decorator will then update the moustache property with it's own bigger moustache and then return the updated clone;
UPDATED to explain cloning: The whole point of the decorator pattern is to hide the new functionality from the wrapped object, so the wrapped object doesn't clone the decorated properties. You call the clone method of the top level decorator. The decorator overrides the Clone method to add it's own functionality in a transparent way.
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();
}
output of this console application is:
Mario, with moustache size: 1
Upgrading...
Mario, with moustache size: 1.2
Upgrading again...
Mario, with moustache size: 1.44
Alternatively if there are a lot of properties to clone the decorator can do this:
public override object Clone()
{
var clone = (Mario)_inner.Clone();
clone.MoustacheSize = this.MoustacheSize;
return clone;
}
The decorator uses the clone method of the original object, and then updates the properties it changes itself. But it's still the decorator that is responsible for the end result.
精彩评论