【问题标题】:Open/Close Principle in OOPSOOPS 中的开/关原则
【发布时间】:2016-09-10 05:33:55
【问题描述】:

我正在从事一个电信项目。我在我的项目中实施了开放/封闭原则。以下是我的课程。

MainServiceClass.CS

public abstract class BaseServiceClass
{
    public abstract IEnumerable<string> GetServiceData();
    public abstract IEnumerable<string> GetDashBoardData();
}

Web_Service.CS

public class WebServiceClass : BaseServiceClass
{
    public override IEnumerable<string> GetServiceData()
    {
        List<string> MyList = new List<string>();
        return MyList;
    }

    public override IEnumerable<string> GetDashBoardData()
    {
        List<string> MyList = new List<string>();
        return MyList;
    }
}

Voice_Service.CS

public class VoiceSericeClass : BaseServiceClass
{
    public override IEnumerable<string> GetServiceData()
    {
        List<string> MyList = new List<string>();
        return MyList;
    }

    public override IEnumerable<string> GetDashBoardData()
    {
        List<string> MyList = new List<string>();
        return MyList;
    }
}

以后如果需要实现Video服务,我会新建一个Video_Service类,相信会实现Open/Close原理。

如果我需要在 MainServiceClass.cs 添加一个新方法,我将添加一个新方法 (GetNewTypeOfData())。

问题:在这里,我正在修改一个类。不过,我在关注 OCP 吗?或者,有什么方法可以在 MainServiceClass.cs 中添加新方法??

请提出建议。

附注我需要在所有派生类(即 Web_Service.cs、Voice_Service.cs 和 Video_Service.cs)中实现此方法

在 CrudaLilium 回复后更新我的问题。

这是我的理解。如果我错了,请纠正我。

我当前的代码:

 public interface IMainBase
{
    IEnumerable<string> GetData2016();
}

public class VoiceService : IMainBase
{
    public IEnumerable<string> GetData2016()
    {
        return Enumerable.Empty<string>();
    }
}

我会在 2017 年得到一个新的要求。所以,我会在 2017 年更新我的代码

public interface IMainBase
{
    IEnumerable<string> GetData2016();
}    

public class VoiceService : IMainBase
{
    public IEnumerable<string> GetData2016()
    { 
        return Enumerable.Empty<string>();
    }
}

//New Code will be Added in 2017....Start

public interface IMainBase2017 : IMainBase
{
    IEnumerable<string> GetData2017();
}

public class voiceService2017 : VoiceService, IMainBase2017
{
    public IEnumerable<string> GetData2017()
    {
        return Enumerable.Empty<string>();
    }
}

//New Code Added be in 2017...Ended

我会在 2018 年再次收到新的要求。所以,我将在 2018 年更新我的代码。

 public interface IMainBase
{
    IEnumerable<string> GetData2016();
}    

public class VoiceService : IMainBase
{
    public IEnumerable<string> GetData2016()
    { 
        return Enumerable.Empty<string>();
    }
}

//New Code will be Added in 2017....Start

public interface IMainBase2017 : IMainBase
{
    IEnumerable<string> GetData2017();
}

public class voiceService2017 : VoiceService, IMainBase2017
{
    public IEnumerable<string> GetData2017()
    {
        return Enumerable.Empty<string>();
    }
}

//New Code Added be in 2017...Ended

//New Code will be Added in 2018...Start

public class WebService2018 : IMainBase2017
{
    public IEnumerable<string> GetData2016()
    {
        return Enumerable.Empty<string>();
    }

    public IEnumerable<string> GetData2017()
    {
        return Enumerable.Empty<string>();
    }
}


//New Code will be Added in 2018...End

按照上面的代码,我没有违反 OCP。这是一个好习惯还是我也有其他方法?

【问题讨论】:

  • 您是说要添加将出现在所有类中的新方法和实现吗?
  • 是的,我想在 MainService 类中添加一个新方法,稍后我将在派生类中覆盖它。
  • 在添加新功能时必须更改现有类时,您将违反 OCP。所以你没有遵循 OCP;你把它弄坏了。
  • @Steven Fine,我明白了。但是你能告诉我如何在 MainService 类中添加一个新方法吗?我应该创建一个接口还是抽象类?请提出建议。
  • 在不破坏 OCP 的情况下,您无法添加新方法。您应该使用新方法创建一个新类。

标签: c# asp.net oop solid-principles design-principles


【解决方案1】:

创建 Video_Service 没有问题,但更改BaseServiceClass 是,您不会遵循原则。

如果将其设为抽象,则需要修改从BaseServiceClass 继承的所有其他类。但是,即使您不使其抽象,这似乎也毫无意义,因为当前所有使用您的 BaseServiceClass 的客户端类都不会使用除了您已经拥有的 2 之外的任何其他方法。

如果您的客户端类需要使用第三种方法,最好创建另一个继承自BaseServiceClass 的抽象类(例如BaseServiceClass2)并在那里添加新方法并使您的客户端依赖于这节课。从那里扩展您现有的类 WebServiceClassVoiceSericeClass 您必须创建新类并从 BaseServiceClass2 继承并使用适配器模式。

示例代码:

    public abstract class BaseServiceClass
    {
        public abstract IEnumerable<string> GetServiceData();
        public abstract IEnumerable<string> GetDashBoardData();
    }

    public abstract class BaseServiceClass2 : BaseServiceClass
    {
        public abstract IEnumerable<string> GetNewTypeOfData();
    }


    public class WebServiceClass2 : BaseServiceClass2
    {
        private BaseServiceClass adaptee;

        WebServiceClass2(BaseServiceClass adaptee)
        {
            this.adaptee = adaptee;
        }

        public override IEnumerable<string> GetDashBoardData()
        {
            return adaptee.GetDashBoardData();
        }

        public override IEnumerable<string> GetNewTypeOfData()
        {
            return Enumerable.Empty<string>();
        }

        public override IEnumerable<string> GetServiceData()
        {
            return adaptee.GetServiceData();
        }
    }

如果你让BaseServiceClass 成为一个接口会更好,如果你需要添加任何新的东西,你只需创建继承自它的新接口,就像前面的例子一样,让你的客户端类依赖于你的新接口,从在那里,您可以创建继承自 WebServiceClassVoiceSericeClass 等的新类并实现新接口。

例子:

    public interface IBaseServiceClass
    {
        IEnumerable<string> GetServiceData();
        IEnumerable<string> GetDashBoardData();
    }

    public interface IBaseServiceClass2 : IBaseServiceClass
    {
        IEnumerable<string> GetNewTypeOfData();
    }


    public class WebServiceClass2 : WebServiceClass, IBaseServiceClass2
    {
        public IEnumerable<string> GetNewTypeOfData()
        {
            return Enumerable.Empty<string>();
        }
    }

    public class WebServiceClass : IBaseServiceClass
    {
        public IEnumerable<string> GetServiceData()
        {
            List<string> MyList = new List<string>();
            return MyList;
        }

        public IEnumerable<string> GetDashBoardData()
        {
            List<string> MyList = new List<string>();
            return MyList;
        }
    }

类/接口名称仅用作占位符,最好以更有意义的方式命名。

【讨论】:

  • 感谢您的回复。我有个问题。问题:今天,我已经在生产服务器上部署了我的项目。明年产生一个需求,所以我需要在 MainService 类中实现一个新方法。所以,我永远不应该违反 OCP 并根据您的建议添加新的接口/类。好的,我会添加它。一段时间后,我可能会收到对新方法的请求。那么,我应该为每个请求生成一个新的抽象/接口吗?
  • 如果我无法解释我的问题,请告诉我,我会详细说明。
  • 是的,您必须创建新接口并创建扩展现有类的新类,但要避免创建上帝类。
  • 什么是神级?
  • god 类/blob/god 对象是做太多事情的类,它是一种反模式。您可能不必继续扩展您的服务类,而是应该创建封装新功能的新类,但这取决于您的客户端类是如何实现的。
猜你喜欢
  • 2021-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-18
  • 1970-01-01
  • 2021-02-01
  • 1970-01-01
  • 2017-12-01
相关资源
最近更新 更多