1

我正在对提供数据的 API 进行更改(这是对我原来的问题的更新)。一些搜索需要有关作者的数据并获取IAuthor对象。API 有一个IAuthor接口和一个具体的实现类,IAuthor称为Author.

Search.GetBooksByAuthor当作者被标记为小说家时,我需要更改该方法的行为以提供不同的语义。我听说过开放/封闭原则,似乎更改IAuthor和/或Author和/或Search类会违反这一点(Book不过,类肯定保持不变)。那么如何进行这个简单的改变呢?

例如,我最初在想这样的事情,但我的想法可能很不稳定,因为它涉及更改Search类:

//Before
class Search 
{
   public Books[] GetBooks(IAuthor author){
       // Call data access GetBooks...
    }
}


//After
class Search
{
   public Books[] GetBooks(IAuthor author){
       // To maintain pre-existing behaviour
       // call data access GetBooks method with SQL param @AsNovelist = false...
       // (or don't pass anything because the SQL param defaults to false)
    }

   public Books[] GetBooksAsNovelist(IAuthor author){
       // To get new behaviour
       // call data access GetBooks method with SQL param @AsNovelist = true
       // so that their non-fiction books are omitted from results
    }
}
4

6 回答 6

1

使用谓词进行过滤怎么样?

class Search
{
   public Books[] GetBooks(IAuthor author, Func<IAuthor, bool> filter){
       // ...
    }
}

search.GetBooks(author, a => a.IsNovelist)
于 2013-01-17T09:12:42.727 回答
1

很明显,为了知道您的作者是否是 a Novelist,必须进行一些更改,您可以通过以下两种方式之一进行操作。理论上你不需要改变任何东西,但是你需要一个新的类。

public class Novelist : Author, IAuthor { }

然后,您可以将小说家传递给您的方法,然后确定您的作者类型。

class Search 
{
   public Books[] GetBooks(IAuthor author){
       if(author is Novelist)
         //Do some stuff or set a flag/bool value
    }
}

或者如前所述,为您的 Author 接口实现一个布尔成员并检查它。但是,上述内容会阻止您更改班级结构。

这意味着您的小说家实际上仍然是作家,只是有自己的类型。您的方法签名保持不变,您的类结构保持不变,您只是有一个“不同类型的作者”的类型,理论上应该没问题。调用如下测试。

GetBooks(new Novelist());
于 2013-01-17T09:16:42.953 回答
1

为了扩展类,C# .NET 在 .NET 3.5 中引入了扩展方法,其主要目的正是在不修改现有代码的情况下扩展类:

public static class SearchExtensions
{
  public static Books[] GetBooksAsNovelist(this Search search, IAuthor author)
  {
     // Perform novelist search
  }
}

然后,您可以正常调用 Search 类:

Search.GetBooksAsNovelist(author);
于 2013-01-17T09:19:26.567 回答
1

您可以使用 C# 语言的扩展功能。

请参阅http://msdn.microsoft.com/en-us/library/vstudio/bb383977.aspx

扩展能够通过保持类的完整性来向类添加功能。

在你的情况下,你可以写成:

public static class SearchExtensions
    {
        public static Books[] GetBooks(this Search search, IAuthor author)
        {
            //new logic
        }
    }   

您可以通过 Search 对象访问此新方法,并且 Search 类也保持不变。

如果您觉得这有帮助,请告诉我。

于 2013-01-17T09:20:25.397 回答
1

您可以使您的类部分能够添加功能性而无需扩展、继承或控制反转:

// file: Search.cs

partial class Search
{
    public Books[] GetBooks(IAuthor author) { ... }
}

// file: Search.Advanced.cs

partial class Search
{
    public Books[] GetBooksAsNovelist(IAuthor author) { ... }
}

结果:

http://i.snag.gy/VowNv.jpg

于 2013-01-17T10:04:09.170 回答
0

将搜索类方法保持为虚拟,因此任何人都可以覆盖它们以创建新行为?

于 2013-01-17T09:13:59.157 回答