我是设计模式的新手,我知道单一责任原则的目的,但不确定100%如何避免很多微小的变化。下面是我的示例:
//very crude implementation
public class Journal
{
private readonly List<string> entries = new List<string>();
private static int count = 0;
public void AddEntry(string text)
{
entries.Add($"{++count}: {text}");
}
public void RemoveEntry(int index)
{
entries.RemoveAt(index);
count--;
}
public void SaveToDisk(string filename)
{
File.WriteAllText(filename, ToString());
}
}
我知道SaveToDisk
方法不应包含在类中,它应该是专用类,例如PersistenceManager
来处理文件保存。
但是为什么我不能将SaveToDisk()
类保留在Journal
类中?如果有任何新要求,例如将日记保存到云,那么我只需添加一个新方法SaveToCloud()
,并且任何依赖的客户端类都可以使用SaveToCloud()
,我唯一需要做的修改就是添加{ SaveToCloud()
类中的{1}},这很好吗?
已编辑:以下是我的修改版本,请找出所有设计错误:
Journal
答案 0 :(得分:2)
封装
通过将持久性代码移到单独的PersistenceManager
类中,可以保证SaveToDisk()
方法不会修改日记帐的任何私有变量,除非使用公共方法和属性。日记。
单一职责
但是为什么不能将SaveToDisk()方法保留在Journal类中?如果有任何新要求,例如将日记保存到云,那么我只需添加一个新方法SaveToCloud(),并且任何依赖的客户端类都可以使用SaveToCloud(),我唯一需要做的修改就是在Journal中添加SaveToCloud()课,这完全可以吗?
将日记保存到云中将需要您维护一些额外的状态-连接字符串,api密钥,也许是blob客户端等。您从哪里获得该状态?
Journal
类中的静态成员SaveToCloud()
方法将其存储为静态成员是相当有限的,您可以运行并发问题。
每次都将参数传递到SaveToCloud()
方法中意味着您需要遍历最初称为SaveToDisk()
的每个类,并对其进行更新以存储所需的参数。这些是您要避免的“很多微小变化”。
如果相反,您使用PersistenceManager
方法创建了Save()
类,则可以将连接字符串等添加到该类,而调用者都不需要更改。
依赖倒置
实体必须依赖抽象而不是依赖。
通过在Journal
类中将其实现为静态方法,可以消除依赖反转的可能性。想要保存日记的类应将其定义为接口:
public interface IPersistenceManager
{
void Save(string name);
}
请注意,结尾不会说ToDisk()
-呼叫者不必在意保存的日志,只要它是 被保存。然后,当您的要求从磁盘上的存储更改为云上的存储时,您无需对调用方进行任何代码更改。
答案 1 :(得分:0)
Journal
类的工作(其唯一职责)是代表期刊。像Journal.saveToDisk()
这样的方法存在的问题是它需要的工作不属于该工作,例如确定要使用的文件名,确保在进程中止时不会留下任何不良状态等。 {1}}类不必知道如何处理磁盘。
您已经认识到,这是不良楔形的细边缘。很快,您将需要一个Journal
,而Journal.saveToCloud()
类也将必须全面了解网络。
在这种情况下,必须将日志工作与磁盘工作分开,以便可以将日志工作放在Journal
类中,而磁盘工作则放在其他位置。
常见的解决方案是添加Journal
,将日记转换为数据,然后将其保存到磁盘,云或其他任何位置。 byte [] Journal.toByteArray()
将执行类似的功能。无论哪种方式,将日记转换为字节序列都是特定于日记的工作,您可以将其放在Journal.writeToStream(Stream target)
类中。
是否需要像持久性管理器之类的东西取决于您应用程序的其余部分。