是否违反LSP后置条件规则?求符合Liskov替换原则的改造方案
Liskov替换原则(LSP)后置条件违规分析与改造方案
问题背景
根据LSP的后置条件规则:
LSP: 后置条件不能被弱化,只能被强化。
现有代码中:
- 父类
ProcessController的GetRunningProcess方法返回不包含application类型的进程集合(包含system和user类型) - 子类
UserProcessController仅返回user类型的进程 - 子类
ApplicationProcessController仅返回application类型的进程
需要确认这两个子类是否存在弱化后置条件的情况,并给出符合LSP要求的改造方案。
原代码实现
public class ProcessController { public virtual Dictionary<int, string> GetRunningProcess() { Dictionary<int, string> processes = new() { { 1, "system" }, { 44, "system" }, { 45, "user" }, { 102, "user" }, { 176, "user" }, { 274, "application" }, { 188, "application" } }; return processes.Where(x => !x.Value.Equals("application")).ToDictionary(); } } public class UserProcessController : ProcessController { public override Dictionary<int, string> GetRunningProcess() { Dictionary<int, string> processes = new() { { 1, "system" }, { 44, "system" }, { 45, "user" }, { 102, "user" }, { 176, "user" }, { 274, "application" }, { 188, "application" } }; Dictionary<int, string> userProcess = processes.Where(x => x.Value.Equals("user")).ToDictionary(); return userProcess; } } public class ApplicationProcessController : ProcessController { public override Dictionary<int, string> GetRunningProcess() { Dictionary<int, string> processes = new() { { 1, "system" }, { 44, "system" }, { 45, "user" }, { 102, "user" }, { 176, "user" }, { 274, "application" }, { 188, "application" } }; Dictionary<int, string> userProcess = processes.Where(x => x.Value.Equals("application")).ToDictionary(); return userProcess; } }
违规分析
UserProcessController 未违反LSP
父类的后置条件是“返回的进程集合不包含application类型”,子类返回的user类型进程完全满足这个条件,并且额外增加了“仅包含user类型”的约束——这属于强化后置条件,符合LSP要求。ApplicationProcessController 违反LSP
父类明确保证返回结果中没有application类型的进程,但子类直接返回了仅包含application类型的集合,完全破坏了父类的后置条件契约——这属于弱化后置条件,违反了LSP规则。
符合LSP的改造方案
核心思路是:避免让功能契约不同的类通过继承绑定,改用接口抽象或基于通用父类的扩展,确保每个类的契约清晰且符合父类/接口的约束。
方案1:使用接口分离
定义统一的进程检索接口,各个控制器独立实现接口,不存在继承关系,从根源上避免LSP冲突:
public interface IProcessRetriever { Dictionary<int, string> GetRunningProcess(); } public class NonApplicationProcessController : IProcessRetriever { public Dictionary<int, string> GetRunningProcess() { var processes = ProcessHelper.GetAllProcesses(); return processes.Where(x => !x.Value.Equals("application")).ToDictionary(); } } public class UserProcessController : IProcessRetriever { public Dictionary<int, string> GetRunningProcess() { var processes = ProcessHelper.GetAllProcesses(); return processes.Where(x => x.Value.Equals("user")).ToDictionary(); } } public class ApplicationProcessController : IProcessRetriever { public Dictionary<int, string> GetRunningProcess() { var processes = ProcessHelper.GetAllProcesses(); return processes.Where(x => x.Value.Equals("application")).ToDictionary(); } } // 提取公共方法,避免代码重复 public static class ProcessHelper { public static Dictionary<int, string> GetAllProcesses() { return new Dictionary<int, string> { { 1, "system" }, { 44, "system" }, { 45, "user" }, { 102, "user" }, { 176, "user" }, { 274, "application" }, { 188, "application" } }; } }
方案2:调整继承层级(若需保留继承)
将父类改为返回所有进程的通用基类,子类通过过滤实现各自的功能,此时父类的后置条件是“返回所有进程”,子类的过滤操作属于强化后置条件:
public class BaseProcessController { protected virtual Dictionary<int, string> GetAllProcesses() { return new Dictionary<int, string> { { 1, "system" }, { 44, "system" }, { 45, "user" }, { 102, "user" }, { 176, "user" }, { 274, "application" }, { 188, "application" } }; } public virtual Dictionary<int, string> GetRunningProcess() { return GetAllProcesses(); } } public class NonApplicationProcessController : BaseProcessController { public override Dictionary<int, string> GetRunningProcess() { var allProcesses = GetAllProcesses(); return allProcesses.Where(x => !x.Value.Equals("application")).ToDictionary(); } } public class UserProcessController : BaseProcessController { public override Dictionary<int, string> GetRunningProcess() { var allProcesses = GetAllProcesses(); return allProcesses.Where(x => x.Value.Equals("user")).ToDictionary(); } } public class ApplicationProcessController : BaseProcessController { public override Dictionary<int, string> GetRunningProcess() { var allProcesses = GetAllProcesses(); return allProcesses.Where(x => x.Value.Equals("application")).ToDictionary(); } }
内容的提问来源于stack exchange,提问作者riki
相关产品推荐
相关产品推荐

