c# 装饰器模式
-
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
-
所以:装饰器和适配器最大得区别在
-
装饰器 是功能不满足 扩展功能
-
适配器 是功能满足 但是需要转换输出
-
https://www.bilibili.com/video/BV194411y7dp?p=7
利用装饰器模式
写如下 缓冲区 代码
思路:
1.继承stream 实现Read(byte[] buffer, int offset, int count)接口 其实就是保持base.read()的调用不变
2.实现自己的一个字节一个字节取得Read()方法
核心:将Stream流通过构造函数传过来
class MyBufferedStream2 : Stream
{
private const int DefaultBufferSize = 163804;
private Stream stream;
private byte[] cb;
private int index;
private int count;
public MyBufferedStream2(Stream stream, int bufferSize)
{
this.stream = stream;
this.cb = new byte[bufferSize];
}
public MyBufferedStream2(Stream stream)
: this(stream, DefaultBufferSize)
{
}
private void EnSureCanOpen()
{
if(stream.CanRead == false)
{
_BufferError.StreamIsColse();
}
}
public override int Read(byte[] buffer, int offset, int count)
{
return stream.Read(buffer, offset, count);
}
public int Read()
{
EnSureCanOpen();
if (count == 0)
{
count = Read(cb, 0, cb.Length);
index = 0;
}
if (count == 0 )
{
unchecked
{
return -1;
//return (byte)-1;
}
}
byte b = cb[index];
index++;
count--;
return b;
}
public override bool CanRead => throw new NotImplementedException();
public override bool CanSeek => throw new NotImplementedException();
public override bool CanWrite => throw new NotImplementedException();
public override long Length => throw new NotImplementedException();
public override long Position { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public override void Flush()
{
throw new NotImplementedException();
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotImplementedException();
}
public override void SetLength(long value)
{
throw new NotImplementedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotImplementedException();
}
}
internal static class _BufferError
{
internal static void StreamIsColse()
{
throw new ObjectDisposedException("file closed");
}
}
调用:
//因为FileStream 自带缓冲区!!!! 所以我们将它改为1
FileStream fs2 = new FileStream(path,FileMode.Open, FileAccess.Read,FileShare.Read,1);
sw.Start();
while ((c = fs2.ReadByte()) != -1)
{
//Console.WriteLine((char)c);
}
fs2.Close();
sw.Stop();
Console.WriteLine((sw.Elapsed.TotalSeconds));
sw.Reset();
MyBufferedStream2 mbs2 = new MyBufferedStream2(new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 1));
sw.Start();
while ((c = mbs2.Read()) != -1)
{
//Console.WriteLine((char)c);
}
sw.Stop();
Console.WriteLine((sw.Elapsed.TotalSeconds));
输出结果
0.032399
0.0012816
测试文件生成:
string path = "c:/abc.txt";
using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write))
{
BufferedStream bfs = new BufferedStream(fs);
byte[] bytes = Encoding.UTF8.GetBytes("hello world\n");
for (int i = 0; i < 1000; i++)
{
bfs.Write(bytes, 0, bytes.Length);
}
bfs.Close();
}
简单 举例2:
namespace Decorator
{
abstract class AbstractRobot
{
public abstract void Walk();
}
internal class MyRobot : AbstractRobot
{
public override void Walk()
{
Console.WriteLine("myrobot walk");
}
}
internal class BaseDecorator : AbstractRobot
{
private AbstractRobot robot;
public BaseDecorator(AbstractRobot robot)
{
this.robot = robot;
}
public override void Walk()
{
robot.Walk();
}
}
internal class RobotDecorator : BaseDecorator
{
public RobotDecorator(AbstractRobot robot) :base( robot) {}
public override void Walk()
{
base.Walk();
Console.WriteLine("after walking ,song a song");
}
public void Laugh()
{
Console.WriteLine("laugh!");
}
}
}
//调用
static void Main(string[] args)
{
AbstractRobot robot = new MyRobot();
RobotDecorator robotDecorator = new RobotDecorator(robot);
//扩展一个功能 让机器人能走完后自动唱歌
robotDecorator.Walk();
robotDecorator.Laugh();
}