1

这是一些伪代码来说明我在看什么。

public class Loader
{
    public Execute()
    {
       var currentPage = new ItemPageDocumentBuilder();
       while(reader.Read())
       {
           currentPage.Add(reader.XmlDoc);
       }
    }

    private class ItemsToLoad
    {
        private XmlDocument _page
        public void Add(XmlElement itemelement)
        {
            _page.DocumentElement.AppendChild(itemElement);
        }
    }
}

我需要从Loader派生一个类,然后在里面重写ItemsToLoad类的Add方法,然后调用base.Execute()。换句话说,我希望派生类的 Execute() 方法与 Loader 的方法完全相同,但要使用 ItemsToLoad 的重写 Add 方法来工作。

我怀疑最巧妙的方法是从 Loader 内部删除 ItemsToLoad,并使其抽象,对吗?

如果我不能这样做,出于兴趣,最好的解决方案是什么?

4

4 回答 4

1

如果我理解您的要求,那么您有两个责任:执行某事(始终相同)和添加某事(不同)。

我会做的更简单,没有继承和内部类。

对于添加任务,您定义一个接口:

public interface IItemAdder
{
    void Add();
}

还有一个或多个实现:

public class ItemAdder1 : IItemAdder
{
    public void Add()
    {            
         // specific implementation here
    }
}

然后,您有一个加载器,您可以在其中注入项目添加器的特定实例:

public class Loader : ILoader
{
    private IItemAdder _itemAdder;
    public Loader(IItemAdder itemAdder)
    {
        _itemAdder = itemAdder;
    }
    public void Execute()
    {
        // use injected item adder to do work
        _itemAdder.Add();
    }       
}

public interface ILoader
{
    void Execute();
}

所以用法是:

var loader = new Loader(new ItemAdder1());
loader.Execute();    

这样所有东西都被注入了,可以很容易地替换和模拟;你清楚地将关注点分开。

于 2013-05-31T12:59:16.827 回答
0

我需要从Loader派生一个类,然后在里面重写ItemsToLoad类的Add方法,然后调用base.Execute()。换句话说,我希望派生类的 Execute() 方法与 Loader 的方法完全相同,但要使用 ItemsToLoad 的重写 Add 方法来工作。

您需要覆盖Loader,而不是ItemsToLoad. 您没有显示使用 的代码ItemsToLoad,因此很难具体说明 - 但至少,您需要覆盖new ItemsToLoad指向您的子类的 。此外,ItemsToLoad是私有的——这意味着你不能在内部使用它Loader。就像现在一样,您需要完全重写并覆盖其中使用ItemsToLoad的每个方法。LoaderItemsToLoad

如果您控制Loader类,最简单的更改可能是抽象出创建ItemsToLoad并打开它,ItemsToLoad以便它可以被子类化。就像是:

public class Loader {
   private ItemsToLoad Items { get; set; }

   protected virtual ItemsToLoad CreateItemsToLoad() {
      return new ItemsToLoad();
   }

   protected class ItemsToLoad {
      public virtual void Add() {
      }
   }
}

public class MyOtherLoader : Loader {
   protected override ItemsToLoad CreateItemsToLoad() {
      return new MyOtherItemsToLoad();
   }

   private class MyOtherItemsToLoad : ItemsToLoad {
      public override void Add() {
      }
   }
}
于 2013-05-31T13:59:48.660 回答
0

这是一个建议(虽然语法可能不正确):

public class Loader
{
    ItemsToLoad item;
    public Loader(ItemsToLoad item) {
      this.item = item;
    }

    public Execute()
    {
       // do things using item like item.add();
    }
}

interface ItemsToLoad
{
    void add();
}

class ItemsToLoad1: ItemsToLoad
{
    void add(){
        // implementation
    }
}

class ItemsToLoad2: ItemsToLoad
{
    void add(){
        // implementation
    }
}

这里是如何使用它们;

ItemsToLoad item;
if (some condition) {
   item = new ItemsToLoad1()
} else {
   item = new ItemsToLoad2()
}

Loader loader = new Loader(item);
loader.execute();
于 2013-05-30T19:56:08.260 回答
0

您可以继承这两个类并将子类对象注入其父类。

class Loader
    {

        public void Execute(ItemsToLoad argObj)
        {
            if(argObj == null)
                argObj = new ItemsToLoad();

            argObj.Add(19);
        }

        public class ItemsToLoad
        {
            public virtual void Add(int a)
            {
                Console.WriteLine("Reached ItemsToLoad.");
            }
        }
    }

class ChildLoader:Loader
    {
        public void Execute(ItemsToLoad argObjLoader)
        {
            if (argObjLoader == null)
                argObjLoader = new ChildItemsToLoad();

            base.Execute(argObjLoader);
    }

    class ChildItemsToLoad : Loader.ItemsToLoad
    {

        public override void Add(int b)
        {
            Console.WriteLine("Reached ChildItemsToLoad.");
        }

    }
}

并且可以开始

ChildLoader obj999 = new ChildLoader();
obj999.Execute(null);
于 2013-05-31T12:33:25.400 回答