C#类间依赖设计合理性及IDisposable实现相关疑问
PersonFinder与Person类设计问题解答
示例代码
PersonFinder类(A类)
public class PersonFinder { // 为简化逻辑,假设每个人的名字唯一 public Person FindPersonByName(string name) { // 查找逻辑省略 return new Person(name, this); } }
Person类(B类)
public class Person { public string Name { get; set; } private string childName { get; set; } // 简化假设:每个人都知道自己孩子的名字 private PersonFinder _personFinder { get; set; } public Person(string name, PersonFinder personFinder) { Name = name; _personFinder = personFinder; } public Person GetChild() { return _personFinder.FindPersonByName(childName); } }
问题1:该设计是否合理?有无更优实现方式?
现有设计的合理性
这个设计基本符合单一职责原则:把Person对象的查找/创建逻辑集中在PersonFinder类,Person只负责自身核心业务逻辑(比如获取子对象),不用关心对象查找细节,一定程度上降低了Person类的复杂度。
但存在明显缺陷:
- 重复创建对象:每次调用
FindPersonByName都会生成新的Person实例,即使同一个名字被多次查找,也会产生重复对象,既浪费内存又可能导致数据不一致。 - 耦合过紧:Person直接依赖PersonFinder具体类而非抽象接口,后续如果要替换查找逻辑(比如从数据库查询改成缓存查询),必须修改Person类代码,违反了依赖倒置原则。
更优实现方案
- 添加对象缓存:在PersonFinder中维护字典缓存已创建的Person实例,避免重复创建:
public class PersonFinder { private readonly Dictionary<string, Person> _personCache = new Dictionary<string, Person>(); public Person FindPersonByName(string name) { if (_personCache.TryGetValue(name, out var existingPerson)) { return existingPerson; } var newPerson = new Person(name, this); _personCache.Add(name, newPerson); return newPerson; } }
- 抽象查找接口:定义
IPersonFinder接口,Person依赖接口而非具体类,提升扩展性:
public interface IPersonFinder { Person FindPersonByName(string name); } public class PersonFinder : IPersonFinder { // 缓存实现同上 } public class Person { private readonly IPersonFinder _personFinder; public Person(string name, IPersonFinder personFinder) { Name = name; _personFinder = personFinder; } // GetChild方法逻辑不变 }
- 优化子对象关联:如果childName需要从外部数据源获取,可在Person构造时直接注入,或者由PersonFinder在创建Person时一并初始化,避免Person类持有未明确初始化的字段。
问题2:若PersonFinder实现了IDisposable,Person类是否需要实现?
Person类不需要实现IDisposable,这并非规则例外,而是对微软IDisposable规则的正确理解:
微软文档的核心规则是:当类拥有IDisposable对象的所有权时,才需要实现IDisposable。这里的“所有权”指该类负责创建对象,或承担其生命周期管理责任(比如决定对象何时释放)。
在你的场景中,PersonFinder是全局共享的唯一实例,其生命周期由上层应用(比如程序启动/退出逻辑)管理,Person类只是持有引用并使用,并不拥有它的所有权。如果Person实现Dispose并释放PersonFinder,会导致其他正在使用该实例的Person对象出现错误(共享实例被提前销毁)。
正确做法是:由创建PersonFinder的上层代码负责调用其Dispose方法,Person类无需处理。
内容的提问来源于stack exchange,提问作者Ramon Thomaz
相关产品推荐
相关产品推荐

