C# 我错过了什么模式
我有以下接口C# 我错过了什么模式,c#,.net,oop,design-patterns,C#,.net,Oop,Design Patterns,我有以下接口 interface IConsoleHistory { void Add(string entry); HistoryEntry GetNextEntry(); HistoryEntry GetPreviousEntry(); void ResetHistoryMarker(); void Delete(HistoryEntry entry); void DeleteEntireHistory(); } public cl
interface IConsoleHistory
{
void Add(string entry);
HistoryEntry GetNextEntry();
HistoryEntry GetPreviousEntry();
void ResetHistoryMarker();
void Delete(HistoryEntry entry);
void DeleteEntireHistory();
}
public class HistoryEntry
{
public HistoryEntry(string value, int index, bool isCommand)
{
Value = value;
Index = index;
IsCommand = isCommand;
}
public string Value { get; private set; }
public int Index { get; private set; }
public bool IsCommand { get; private set; }
}
基于此,我实现了InMemoryHistory:
public class InMemoryHistory : IConsoleHistory
{
protected List<string> History { get; private set; }
private int _currentIndex;
public InMemoryHistory() :this(new List<string>())
{
}
protected InMemoryHistory(List<string> history)
{
History = history;
_currentIndex = -1;
}
public virtual void Add(string entry)
{
History.Insert(0, entry);
}
public HistoryEntry GetNextEntry()
{
if (GetHighestIndex() > _currentIndex)
{
_currentIndex++;
return ReturnAtIndex(_currentIndex);
}
return null;
}
private int GetHighestIndex()
{
return History.Count - 1;
}
private int GetLowestIndex()
{
return History.Count > 0 ? 0 : -1;
}
public HistoryEntry GetPreviousEntry()
{
if (_currentIndex > GetLowestIndex())
{
_currentIndex--;
return ReturnAtIndex(_currentIndex);
}
_currentIndex = -1;
return null;
}
private HistoryEntry ReturnAtIndex(int index)
{
return new HistoryEntry(History[index], index, false);
}
public void ResetHistoryMarker()
{
_currentIndex = -1;
}
public void Delete(HistoryEntry entry)
{
if (History.ElementAtOrDefault(entry.Index) != null)
{
History.RemoveAt(entry.Index);
}
}
public void DeleteEntireHistory()
{
History.Clear();
}
}
MemoryHistory中的公共类:IConsoleHistory
{
受保护列表历史记录{get;private set;}
私有int_currentIndex;
public InMemoryHistory():此(新列表())
{
}
受保护的内存历史记录(列表历史记录)
{
历史=历史;
_currentIndex=-1;
}
公共虚拟空添加(字符串条目)
{
历史记录。插入(0,条目);
}
公共历史条目GetNextEntry()
{
如果(GetHighestIndex()>\u currentIndex)
{
_currentIndex++;
返回索引(_currentIndex);
}
返回null;
}
私有int GetHighestIndex()
{
返回历史。计数-1;
}
private int GetLowestIndex()
{
返回历史记录。计数>0?0:-1;
}
公共历史条目GetPreviousEntry()
{
如果(_currentIndex>GetLowestIndex())
{
_当前索引--;
返回索引(_currentIndex);
}
_currentIndex=-1;
返回null;
}
私有历史条目返回索引(int索引)
{
返回新的HistoryEntry(历史[索引],索引,false);
}
public void ResetHistoryMarker()
{
_currentIndex=-1;
}
公共作废删除(历史记录条目)
{
if(History.ElementAtOrDefault(entry.Index)!=null)
{
历史.RemoveAt(entry.Index);
}
}
public void deleteEntityHistory()
{
历史;
}
}
现在我想要一个基于文件的历史记录。为了保持代码的干性,我想继承InMemoryHistory,并在每次添加后保留整个列表
public class FileBasedHistory : InMemoryHistory
{
private readonly string _fileName;
public FileBasedHistory():this("history.txt")
{
}
public FileBasedHistory(string fileName) :base(GetHistoryFromFile(fileName))
{
_fileName = fileName;
}
public override void Add(string entry)
{
base.Add(entry);
WriteToDisk();
}
private void WriteToDisk()
{
using(var textWriter = new StreamWriter(_fileName, false, Encoding.UTF8))
{
History.ForEach(textWriter.WriteLine);
}
}
private static List<string> GetHistoryFromFile(string fileName)
{
if (!File.Exists(fileName))
return new List<string>();
return File
.ReadAllLines(fileName)
.ToList();
}
}
公共类FileBasedHistory:InMemoryHistory
{
私有只读字符串\u文件名;
public FileBasedHistory():此(“history.txt”)
{
}
public FileBasedHistory(字符串文件名):base(GetHistoryFromFile(文件名))
{
_fileName=文件名;
}
公共覆盖无效添加(字符串条目)
{
添加(条目);
WriteToDisk();
}
私有void WriteToDisk()
{
使用(var textWriter=newstreamWriter(_fileName,false,Encoding.UTF8))
{
历史.ForEach(textWriter.WriteLine);
}
}
私有静态列表GetHistoryFromFile(字符串文件名)
{
如果(!File.Exists(fileName))
返回新列表();
返回文件
.ReadAllLines(文件名)
.ToList();
}
}
这就像一个咒语。但让我困扰的是,我需要静态GetHistoryFromFile
方法。这并不是什么大问题,但我想知道我是否错过了一个更适合这种情况的模式
更新
正如基思已经建议的那样。这也是让我有点困扰的继承方法。继承应该始终是一个问题
您不能说:“基于文件的历史是内存历史中的历史”
所以我想知道我是否应该尝试使用这个策略模式。或者编写一个抽象控制台,实现部分逻辑,但为扩展留出空间。有没有关于如何重构它的建议?我想你已经做得非常完美了
GetHistoryFromFile
只适用于FileBasedHistory
,因此它应该在那里是有意义的。我认为您已经拥有了它GetHistoryFromFile
仅适用于FileBasedHistory
,因此它应该在那里是有意义的。我觉得奇怪的是,您以构造函数的身份传递列表。你根本不必那样做
与其将GetHistoryFromFile视为创建一个新列表,不如将其视为加载到现有列表中的一种方法(这样也会变得更有用……因为它可以将多个文件加载到历史中)
此外,删除和清除操作无法正常写入磁盘
此外,将一行一行写入磁盘可能会变得非常缓慢
此外,InMemory和基于文件的存储可能同时受到耦合的影响。这意味着,虽然他们目前是相似的,但他们很可能会出现分歧。例如,如果基于磁盘的系统使用滚动历史文件和缓存历史。因此,不要过于依赖InMemory和文件而保留在继承结构中,将它们分开可能更容易我觉得奇怪的是,您以构造函数的身份传入了一个列表。你根本不必那样做 与其将GetHistoryFromFile视为创建一个新列表,不如将其视为加载到现有列表中的一种方法(这样也会变得更有用……因为它可以将多个文件加载到历史中) 此外,删除和清除操作无法正常写入磁盘 此外,将一行一行写入磁盘可能会变得非常缓慢
此外,InMemory和基于文件的存储可能同时受到耦合的影响。这意味着,虽然他们目前是相似的,但他们很可能会出现分歧。例如,如果基于磁盘的系统使用滚动历史文件和缓存历史。因此,不要过于依赖InMemory和文件而保留在继承结构中,将它们分开可能更容易您可以在此处使用
迭代器。这三种方法仅用于迭代数据:
HistoryEntry GetNextEntry();
HistoryEntry GetPreviousEntry();
void ResetHistoryMarker();
这些方法用于管理数据:
void Add(string entry);
void Delete(HistoryEntry entry);
void DeleteEntireHistory();
我认为这是一个不同的职责,我将它们转移到了不同的类。您可以在这里使用迭代器。这三种方法仅用于迭代数据:
HistoryEntry GetNextEntry();
HistoryEntry GetPreviousEntry();
void ResetHistoryMarker();
这些方法用于管理数据:
void Add(string entry);
void Delete(HistoryEntry entry);
void DeleteEntireHistory();
我认为这是一种不同的责任,我把他们转移到了不同的班级。是静态让我感到不安。是静态让我感到不安。我想