Decorator Pattern Code Review
Code Download
Define the Decorated Stream Object
Define the StreamDecorator class which "decorates" the built-in Stream .NET class.
class StreamDecorator : Stream
{
Stream m_stream;
Int32 m_totalBytesRead = Int32.MinValue;
Int32 m_numBytesToRead = Int32.MinValue;
Int32 m_maxBytesToRead = 5;
String m_readText = String.Empty;
public StreamDecorator(Stream s)
{
this.m_stream = s;
this.m_totalBytesRead = 0;
this.m_numBytesToRead = (Int32)s.Length;
}
public override bool CanRead
{
get { return this.m_stream.CanRead; }
}
public override bool CanSeek
{
get { return this.m_stream.CanSeek; }
}
public override bool CanWrite
{
get { return this.m_stream.CanWrite; }
}
public override void Flush()
{
this.m_stream.Flush();
}
public override long Length
{
get { return this.m_stream.Length; }
}
public override long Position
{
get
{
return this.m_stream.Position;
}
set
{
this.m_stream.Position = Position;
}
}
public override int Read(byte[] buffer, int offset, int count)
{
return this.m_stream.Read(buffer, offset, count);
}
public override long Seek(long offset, SeekOrigin origin)
{
return this.m_stream.Seek(offset, origin);
}
public override void SetLength(long value)
{
this.m_stream.SetLength(value);
}
public override void Write(byte[] buffer, int offset, int count)
{
this.m_stream.Write(buffer, offset, count);
}
The StreamDecorator class inherits from the Stream base class and implements the standard class functionality.
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 this.m_readText; }
}
public Int32 MaxBytesToRead
{
get
{
return this.m_maxBytesToRead;
}
set
{
this.m_maxBytesToRead = value;
}
}
public Int32 NumBytesToRead
{
get { return this.m_numBytesToRead; }
}
public Int32 TotalBytesRead
{
get { return this.m_totalBytesRead; }
}
public int Read(byte[] buffer)
{
try
{
Int32 numBytesRead = Int32.MinValue;
Int32 maxBytesToRead = this.m_maxBytesToRead;
UTF7Encoding byteString = new UTF7Encoding();
if (this.m_numBytesToRead < maxBytesToRead)
{
maxBytesToRead = this.NumBytesToRead;
}
numBytesRead = this.m_stream.Read(buffer, this.m_totalBytesRead, maxBytesToRead);
this.m_totalBytesRead += numBytesRead;
this.m_numBytesToRead = ((Int32)this.Length) - this.m_totalBytesRead;
this.m_readText = byteString.GetString(buffer);
return m_numBytesToRead;
}
catch
{
throw;
}
}
}
Use the Decorator Pattern
Create an instance of the Stream class (object) and pass it as a parameter to the StreamDecorator class (object).
Stream fStrm = null;
StreamDecorator dStrm = null;
Byte[] bytes;
Int32 bytesToRead;
try
{
this.textBox1.Text = String.Empty;
this.textBox1.Refresh();
fStrm = new FileStream("streamDecorator.txt", FileMode.Open, FileAccess.Read);
dStrm = new StreamDecorator(fStrm);
bytes = new Byte[dStrm.Length];
bytesToRead = dStrm.NumBytesToRead;
dStrm.MaxBytesToRead = 50;
progressBar1.Minimum = 0;
progressBar1.Maximum = dStrm.NumBytesToRead;
while (bytesToRead > 0)
{
bytesToRead = dStrm.Read(bytes);
progressBar1.Value = dStrm.TotalBytesRead;
this.label2.Text = dStrm.TotalBytesRead.ToString();
this.label2.Refresh();
}
this.textBox1.Text = dStrm.ReadText;
this.textBox1.Refresh();
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
dStrm.Close();
fStrm.Close();
}
Invoke the standard Stream methods, as well as, the new custom operations in the StreamDecorator class (object).