开闭原则

作者: 好大一只龍 | 来源:发表于2017-05-15 11:14 被阅读36次

    这是SOLID原则这一系列的第三篇文章,主要来描述开闭(OCP)原则。OCP指出“所有的类或者类似的源代码应该对拓展开放,对修改关闭”。“对拓展开放”意思是你应该设计你的类,以便于有新需求的时候新增新的功能。“对修改关闭”意思是一旦你开发完一个类就不能再修改, 除非是修复bug。
      原则的两个部分似乎是矛盾的。可是如果你正确的组织你的类和依赖关系,你无需修改现存代码就可以新增功能。通常你达到这个目的要通过参考抽象依赖关系,比如接口或抽象类而不是使用具体类。 这样的接口一旦开发完就被固定,所以依赖于它们的类可以依赖于不变的抽象。通过创建新的类实现接口添加新功能。应用OCP到你的项目中,一旦源码经过编写、测试以及调试,将被限制修改。这降低了现存代码引入新bug的风险,使得软件更加健壮。使用接口进行依赖的另外一个作用是减少了耦合性,并且增加了灵活性。

    示例代码

    为了演示OCP的应用,我们可以考虑一些违反它的C#代码,并解释如何重构类遵循以下原则:

    public class Logger
    {
        public void Log(string message, LogType logType)
        {
            switch (logType)
            {
                case LogType.Console:
                    Console.WriteLine(message);
                    break;
     
                case LogType.File:
                    // Code to send message to printer
                    break;
            }
        }
    }
     
     
    public enum LogType
    {
        Console,
        File
    }
    

    上述示例代码是用于记录消息的基本模块。 Logger类具有接受要记录的消息和要执行的日志记录类型的单一方法。 switch语句根据程序是否将消息输出到控制台或默认打印机来更改操作。

    重构代码

    我们可以轻松重构logging代码,以实现符合OCP原则。首先我们需要移除LogType枚举。因为这会限制可以包含的Logging类型。而不是传递type到logger,我们将为我们需要的每一种消息logger创建一个新类。在最后的代码中,我们将有两个这样的类,命名为“ConsoleLogger”和“PrinterLogger”。之后可以添加其他的logger类型,而无需修改现存的代码。Logger类仍然执行所有日志记录,但使用上述消息记录器类之一来输出消息。为了减少类的耦合性,每个消息类都实现IMessageLogger接口。Logger类从来不知道使用的日志记录的类型,因为它的依赖关系使用构造函数注入作为IMessageLogger实例提供。
    重构代码如下:

    public class Logger
    {
        IMessageLogger _messageLogger;
     
        public Logger(IMessageLogger messageLogger)
        {
            _messageLogger = messageLogger;
        }
     
        public void Log(string message)
        {
            _messageLogger.Log(message);
        }
    }
     
     
    public interface IMessageLogger
    {
        void Log(string message);
    }
     
     
    public class ConsoleLogger : IMessageLogger
    {
        public void Log(string message)
        {
            Console.WriteLine(message);
        }
    }
     
     
    public class PrinterLogger : IMessageLogger
    {
        public void Log(string message)
        {
            // Code to send message to printer
        }
    }
    

    相关文章

      网友评论

        本文标题:开闭原则

        本文链接:https://www.haomeiwen.com/subject/xhgcxxtx.html