6

我今天刚刚学到了一些关于Composition over Inheritance的知识。我想知道我是否应该将这个概念应用到我最近写的东西上。

我们之前有两个几乎相同的类,除了一些小的差异。它们包含一些基本的数据库访问功能,但对不同(但相关)的对象类型进行操作。因此,我们之前的课程结构如下:

class BallMillDBHandler{

    public BallMillDBHandler(){ ... }

    public void InsertTool(BallMill tool) { ... }
    public BallMill QueryTool(string toolID) { ... }
    public void UpdateTool(BallMill tool) { ... }
    public void DeleteTool(string toolID) { ... }
}

class DiamondToolDBHandler{

    public DiamondToolDBHandler(){ ... }

    public void InsertTool(DiamondTool tool) { ... }
    public DiamondTool QueryTool(string toolID) { ... }
    public void UpdateTool(DiamondTool tool) { ... }
    public void DeleteTool(string toolID) { ... }
}

我采用了大部分几乎重复的方法并将它们重构为一个BaseToolDBHandler()类,并从其他两个继承它,提供一些抽象方法和属性来处理访问数据库参数本身的差异。

BaseToolDBHandler将辅助类改为包含在数据库访问器中并为它们提供先前抽象属性/方法的通用接口是否有意义?还是我应该把它作为继承的情况?

4

4 回答 4

3

继承确实倾向于被过度使用,但这似乎是一个合适的案例。在许多情况下,人们只是看到重复代码并认为“我将使用继承通过基类删除重复代码”。实际上,大多数重复的代码都可以完全重构为另一个在多个地方使用的类。通常使用它的类不是“相关的”,它们正在做两件完全不同的事情,只是碰巧分享了做一些(或一些系列)小任务的需要。

当你真的可以说类“是”基类的一个实例时,应该使用继承,而不仅仅是一些需要访问在其他地方定义的一堆方法的类。在您的特定情况下,很明显这两个类都是数据库处理程序。在关键点上,它们都服务于相同的总体目标,但它们是该目标的两种不同的可能实现方式。我在这里可以看到的唯一问题(鉴于您没有显示任何方法的内容)是您可以将两个类组合成一个类,但我们需要了解更多关于细节的信息知道这是否可行或可取。

于 2012-09-25T14:35:25.093 回答
3

这看起来像是通过基类/接口使泛型和继承受益的场景。

class DBHandler<TTool> where TTool : ToolBase // or ITool
{
    public DBHandler(){ ... }

    public void InsertTool(TTool tool) { ... }
    public TTool QueryTool(string toolID) { ... }
    public void UpdateTool(TTool tool) { ... }
    public void DeleteTool(string toolID) { ... }
}

如果需要,您可以创建一个基类(可选抽象)或一个接口用作类型约束,以保证您需要工具在方法主体内具有的某些成员。

例子:

var handler = new DBHandler<BallMill>();
BallMill value = handler.QueryTool("xyz");
value.SomeProperty = "New Value";
handler.UpdateTool(value);
于 2012-09-25T14:36:00.293 回答
0

我会说这绝对是继承的任务......但让我们先搞清楚一件事。组合是一种设计模式,可以而且应该在类的多重继承不是给定语言的特性(例如 C#)的情况下使用

组合意味着您的 Composite 类实例化类,通常它们会被继承。在这种情况下,您通过接口向实现提供合同。

为了给你一个关于如何将继承应用到你的代码的粗略例子,考虑一下:(这不是使用组合)

public interface IHandler
{
    void InsertTool(ITool tool);
    void UpdateTool(ITool tool);
    void DeleteTool(string toolID);
    //void DeleteTool(ITool tool) - seems more consistent if possible!?

    ITool QueryTool(string toolID);
}

public interface ITool
{

}

class BallMill : ITool
{
}

class DiamondTool : ITool
{
}

class BallMillDBHandler : IHandler
{

    public BallMillDBHandler(){ ... }

    public void InsertTool(ITool tool) { ... }
    public BallMill QueryTool(string toolID) { ... }
    public void UpdateTool(ITool tool) { ... }
    public void DeleteTool(string toolID) { ... }
}

class DiamondToolDBHandler : IHandler
{

    public DiamondToolDBHandler(){ ... }

    public void InsertTool(ITool tool) { ... }
    public DiamondTool QueryTool(string toolID) { ... }
    public void UpdateTool(ITool tool) { ... }
    public void DeleteTool(string toolID) { ... }
}
于 2012-09-25T14:39:14.983 回答
0

与其继承,不如使用泛型。您想对不同类型的对象执行相同的操作,这正是泛型最擅长的。

于 2012-09-25T14:40:05.873 回答