» The role of the Decorator pattern is to provide a way of attaching new state and behaviour to an object dynamically; the object does not know it is being "decorated", which makes this a useful pattern for evolving systems; » A key implementation point in the Decorator pattern is that decorators both inherit the original class and contain an instantiation of it; the client can use the original component and Decorator component interchangeably; » Each Decorator contains a component object, which might itself be a Decorator; » The Decorator pattern's key feature is that it does not rely on inheritance for extending behaviour; » Decorators do not need any advanced language features; they rely on object aggregation and interface implementation; » An important point about the Decorator pattern is that it is based around new objects being created with their own sets of operations; some of these might be inherited, but only down one level.
Use When:
» Have an existing component class that may be unavailable for subclassing; » Want to attach additional state or behaviour to an object dynamically; » Want to make changes to some objects in a class without affecting others; » Want to avoid subclassing because too many classes could result.
//Define the Decorated Stream Object.
//Define the StreamDecorator class which "decorates" the built-in Stream .NET class. //The StreamDecorator class inherits from the Stream base class and implements the standard class functionality. public classStreamDecorator : Stream { Stream _mStream; int _mTotalBytesRead; int _mNumBytesToRead; int _mMaxBytesToRead = 5; string _mReadText = string.Empty;
public override bool CanRead { get { return _mStream.CanRead; } }
public override bool CanSeek { get { return _mStream.CanSeek; } }
public override bool CanWrite { get { return _mStream.CanWrite; } }
public override void Flush() { _mStream.Flush(); }
public override long Length { get { return _mStream.Length; } }
public override long Position { get { return _mStream.Position; } set { _mStream.Position = Position; } }
public override int Read(byte[] buffer, int offset, int count) { return _mStream.Read(buffer, offset, count); }
public override long Seek(long offset, SeekOrigin origin) { return _mStream.Seek(offset, origin); }
public override void SetLength(long value) { _mStream.SetLength(value); }
public override void Write(byte[] buffer, int offset, int count) { _mStream.Write(buffer, offset, count); }
//The StreamDecorator class then defines additional operations that form part of the new "decorated" class. //These new operations are not available in the standard Stream class. public string ReadText { get { return _mReadText; } }
public int MaxBytesToRead { get { return _mMaxBytesToRead; } set { _mMaxBytesToRead = value; } }
public int NumBytesToRead { get { return _mNumBytesToRead; } }
public int TotalBytesRead { get { return _mTotalBytesRead; } }
public intpublic int Read(byte[] buffer) { int numBytesRead; var maxBytesToRead = _mMaxBytesToRead; UTF7Encoding byteString = newUTF7Encoding(); if (_mNumBytesToRead < maxBytesToRead) { maxBytesToRead = NumBytesToRead; }
//Define the StreamDecorator class which "decorates" the built-in Stream .NET class. //The StreamDecorator class inherits from the Stream base class and implements the standard class functionality. public classStreamDecorator : Stream { Stream _mStream; int _mTotalBytesRead; int _mNumBytesToRead; int _mMaxBytesToRead = 5; string _mReadText = string.Empty;
public override bool CanRead { get { return _mStream.CanRead; } }
public override bool CanSeek { get { return _mStream.CanSeek; } }
public override bool CanWrite { get { return _mStream.CanWrite; } }
public override void Flush() { _mStream.Flush(); }
public override long Length { get { return _mStream.Length; } }
public override long Position { get { return _mStream.Position; } set { _mStream.Position = Position; } }
public override int Read(byte[] buffer, int offset, int count) { return _mStream.Read(buffer, offset, count); }
public override long Seek(long offset, SeekOrigin origin) { return _mStream.Seek(offset, origin); }
public override void SetLength(long value) { _mStream.SetLength(value); }
public override void Write(byte[] buffer, int offset, int count) { _mStream.Write(buffer, offset, count); }
//The StreamDecorator class then defines additional operations that form part of the new "decorated" class. //These new operations are not available in the standard Stream class. public string ReadText { get { return _mReadText; } }
public int MaxBytesToRead { get { return _mMaxBytesToRead; } set { _mMaxBytesToRead = value; } }
public int NumBytesToRead { get { return _mNumBytesToRead; } }
public int TotalBytesRead { get { return _mTotalBytesRead; } }
public intpublic int Read(byte[] buffer) { int numBytesRead; var maxBytesToRead = _mMaxBytesToRead; UTF7Encoding byteString = newUTF7Encoding(); if (_mNumBytesToRead < maxBytesToRead) { maxBytesToRead = NumBytesToRead; }