【问题标题】:design pattern for the case of abstract class with inheriting classes with empty implementation methods抽象类具有空实现方法的继承类的设计模式
【发布时间】:2019-08-06 12:36:00
【问题描述】:

您能否为以下场景推荐一个好的实践模式: 我有一个定义公共行为的基本抽象类和两个继承类,每个继承类都定义了一组方法,这些方法不同于另一个实现。 然后在创建代码中(假设通过配置)我为每种配置设置选择我想要的实现并调用“doWork”,我的问题是如何避免继承类中的“空”实现以防继承类选择不实现该方法。

abstract class CommonParentClass{
    public void doWork()
    {
      commonA();
      commonB();
      uniqueA();
      uniqueB();
    }
    internal  void commonA()
    {
        //do work which is same for inheriting classes
    }
    internal void commonB()
    {
       //do work which is same for inheriting classes
    }   
    abstract void uniqueA(); 
    abstract void uniqueB();
    abstract void uniqueC();    
}

class FirstChildClass:CommonParentClass
{
        protected void uniqueA()
        {
            //implementation specific to first child
        }
        protected void uniqueB()
        {
            //EMPTY
        }   
        protected void uniqueC()
        {
            //implementation specific to first child
        }       
}

class SecondChildClass:CommonParentClass
{
        protected void uniqueA()
        {
            EMPTY
        }
        protected void uniqueB()
        {
            //implementation specific to second child
        }
        protected void uniqueC()
        {
            //implementation specific to second child
        }       
}

我有大约 5/6 的方法在其中一个继承类中是空的。 我应该使用什么设计模式来克服这个问题并避免代码重复?

【问题讨论】:

  • internal common()abstract unique() 在继承类中具有唯一代码。不要让你的基类知道继承类。
  • 如何使用继承 CommonParentClass 的非抽象 CommonParentClassBase 与 uniqueA、uniqueB 和 uniqueC 作为虚拟成员?
  • “避免空实现”是什么意思?如果您不想要求子类实现方法(或显式提供空实现),请不要将它们标记为抽象。如果您确实需要它,请将它们保留为抽象的。
  • 所以假设我的电话是 CommonClass c=new FirstChildClass(); c.doWork();
  • 在这种情况下你不能真正强制执行。您的选择是 1) 不允许覆盖该方法 2) 提供默认实现并可选择允许覆盖它或 3) 要求覆盖和实现该方法。除此之外,您无法真正控制开发人员选择实现该方法的方式。

标签: c# design-patterns


【解决方案1】:

鉴于所有这些函数似乎都具有相同的签名,您可以使用Actions 的列表。

abstract class CommonParent
{
    private readonly List<Action> _funcs = new List<Action>();

    private void CommonA() { }
    private void CommonB() { }

    protected void AddAction(Action action) => _funcs.Add(action);

    protected CommonParent()
    {
        _funcs.Add(CommonA);
        _funcs.Add(CommonB);
    }

    internal void Execute()
    {
        foreach(Action action in _funcs)
            action();
    }
}

class FirstChildClass : CommonParent
{
    private void UniqueA() { }
    private void UniqueB() { }
    private void UniqueC() { }
    public FirstChildClass()
    {
        AddAction(UniqueA);
        AddAction(UniqueB);
        AddAction(UniqueC);
    }
}


class SecondChildClass : CommonParent
{
    private void UniqueD() { }
    private void UniqueE() { }
    private void UniqueF() { }
    public SecondChildClass()
    {
        AddAction(UniqueD);
        AddAction(UniqueE);
        AddAction(UniqueF);
    }
}

【讨论】:

  • 签名只是为了解释。真正的签名更复杂。
  • @mary,他们有什么不同?他们能否采用共同的结构或类并使用他们需要的部分?你的实际用例是什么?
  • 他们得到不同的参数并返回不同的类型: SetScanId(scanId);初始化扫描目录(扫描路径); CreateLogStatusLib(); SetupLogs(scanId); SetProcessPriority(); InitializeScanId(); string[] projectFilesPaths = LoadProject();扫描文件(项目文件路径);
  • 调用的顺序很重要。所以假设我想先制作 commonA 然后 uniqueA 第二 commonB 第三和 uniqueB 第四
猜你喜欢
  • 2013-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-09
  • 1970-01-01
  • 2015-05-21
  • 1970-01-01
  • 2014-02-17
相关资源
最近更新 更多