Skip to content

Instantly share code, notes, and snippets.

@onlytiancai
Last active August 29, 2015 14:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save onlytiancai/d8574e1839867cbdbc9c to your computer and use it in GitHub Desktop.
Save onlytiancai/d8574e1839867cbdbc9c to your computer and use it in GitHub Desktop.
BufferBase
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace BufferBaseLib
{
public interface IBufferState
{
void Commit();
}
public interface IBuffer
{
IBufferState CaptureState();
}
public abstract class BufferBase<T> : IBuffer
{
private readonly object _gate = new object();
private List<T> _items;
public class BufferState : IBufferState
{
private BufferBase<T> _buffer;
private IList<T> _items;
public BufferState(BufferBase<T> buffer, IList<T> items)
{
this._buffer = buffer;
this._items = items;
}
public void Commit()
{
if (this._items.Count > 0)
{
this._buffer.Flush(this._items);
}
}
}
public void Add(T item)
{
lock (_gate)
{
if (_items == null)
{
_items = new List<T>();
}
_items.Add(item);
}
}
public IBufferState CaptureState()
{
List<T> items;
lock (_gate)
{
items = _items;
_items = null;
}
return new BufferState(this, items);
}
protected abstract void Flush(IList<T> items);
}
public class LogBuffer : BufferBase<string>
{
protected override void Flush(IList<string> items)
{
foreach (string item in items)
{
Console.WriteLine("LogBuffer Flush:{0}", item);
}
}
}
class Program
{
static void Main(string[] args)
{
LogBuffer logBuff = new LogBuffer();
new Thread(() =>
{
while (true)
{
logBuff.Add(string.Format("add thread 1: {0}", DateTime.Now));
Thread.Sleep(100);
}
}).Start();
new Thread(() =>
{
while (true)
{
logBuff.Add(string.Format("add thread 2: {0}", DateTime.Now));
Thread.Sleep(100);
}
}).Start();
new Thread(() =>
{
while (true)
{
logBuff.CaptureState().Commit();
Thread.Sleep(1000);
}
}).Start();
Console.ReadKey();
}
}
}
@onlytiancai
Copy link
Author

简化了一下

// 去掉所有接口,只用一个BufferBase基类就够了,Flush(IList<T>)方法当做模板方法,新增一个Flush()
// 库的扩展者只需要继承BufferBase,重写模板方法就行了
// 库的使用者只有Add和Flush两个接口,屏蔽掉CaptureState这些细节,防止用户调用了CaptureState没调用Commit,丢了日志
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace BufferBaseLib
{

    public abstract class BufferBase<T>
    {
        private readonly object _gate = new object();
        private List<T> _items;

        public void Add(T item)
        {
            lock (_gate)
            {
                if (_items == null)
                {
                    _items = new List<T>();
                }

                _items.Add(item);
            }
        }

        public void Flush()
        {
            List<T> items;
            lock (_gate)
            {
                items = _items;
                _items = null;
            }
            this.Flush(items);
        }

        protected abstract void Flush(IList<T> items);
    }

    public class LogBuffer : BufferBase<string> 
    {
        protected override void Flush(IList<string> items)
        {
            foreach (string item in items)
            {
                Console.WriteLine("LogBuffer Flush:{0}", item);
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            LogBuffer logBuff = new LogBuffer();

            new Thread(() =>
            {
                while (true)
                {
                    logBuff.Add(string.Format("add thread 1: {0}", DateTime.Now));
                    Thread.Sleep(100);
                }
            }).Start();

            new Thread(() =>
            {
                while (true)
                {
                    logBuff.Add(string.Format("add thread 2: {0}", DateTime.Now));
                    Thread.Sleep(100);
                }
            }).Start();

            new Thread(() =>
            {
                while (true)
                {
                    logBuff.Flush();
                    Thread.Sleep(1000);
                }
            }).Start();

            Console.ReadKey();
        }
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment