2

我有一个仓库。有时我想通过名称查找框位置,有时通过描述,有时通过 UPC,也许还有其他东西等。这些查找方法中的每一个都调用相同的各种私有方法来查找信息以帮助定位数据。

例如,upc 调用一个私有方法来查找 rowid,name 也是如此,X 也是如此。所以我需要为所有这些方法提供该方法。我可能会以某种方式使用该 rowid 来查找货架位置(这只是一个示例。)

但我的问题是我是否应该有一个抽象类(或其他东西),因为我正在以不同的方式查找我的盒子。

换句话说,假设我的查找代码对于 UPC 和位置非常相似。每个方法都可以使用 (select * from xxxx where location =,或 select * from xxxx where upc =) 调用。我可以在同一个类中创建两个不同的方法

LocateByUPC(string upc)...
LocateByLocation(string location)...
LocateByDescription(string description)

...再次,这将是一个大类

有什么理由我想要一个可以举行的超级课程

abstract class MySuper
{

properties...

LocateBox(string mycriteria)...

}

然后继承它并创建第二个类来覆盖我需要的任何版本的 LocateBox 方法?

我不知道为什么我想这样做,除了看起来 OOD,这真的意味着如果我有充分的理由我想这样做。但是,我知道没有优势。我只是发现我的类变得越来越大,我只是稍微改变了方法的名称和一些代码,这让我觉得继承可能会更好。

如果这很重要,请使用 C#。

编辑 - 如果我只给某人一个没有源但类定义的 .dll,我会这样做吗?类定义。会告诉我的属性等以及要覆盖的方法。

4

8 回答 8

2

两者都不

使用抽象类和接口都不会简化协议,也就是说,你最终还是会得到一堆 LocateXXX 方法

我建议使用通用的 Locate(string criteria) 方法作为基础,并且只为你知道你会经常使用的方法定义专门的方法签名;如果您需要,泛型可以成为未来扩展的全部内容(并且依赖泛型可以简化编码和测试)

于 2009-03-25T18:33:15.080 回答
1

听起来您可能想要实现称为模板方法的设计模式。基本上,您会将基类中的查找算法的大纲定义为最终方法,并将公共代码放在这些方法中。对于根据类型需要不同行为的方法,只需让基类的最终方法调用子类中的受保护方法,并让每个子类实现该行为。

你可以在网上看一些资源,只需在 google 上搜索 Template Method 设计模式。希望它能对您的问题有所启发。

于 2009-03-25T18:27:51.957 回答
0

当您有多个实现时,抽象会有所帮助。并且为了面向未来(希望会出现更新的实现)。接口充当客户端和实现者之间的契约。这是一个不变量。实现可以自由地添加他们希望的任意数量的方法。你有这样的需求吗?

这有助于回答你的问题吗?

于 2009-03-25T18:20:46.187 回答
0

你提出的是(基本上)策略模式。我不喜欢链接到维基百科,但至少它是一个很好的起点。看看利弊,看看它是否对你有益。

我不认为你真的需要这样做。您可以简单地将 LocateBox 方法设为公开,并让它根据您想要执行的搜索调用私有助手。仅仅为了使用一些 OO 设计原则而过度复杂化你的类结构通常是一个坏主意。等到你发现需要它们,然后适当地重构。这将有助于指出什么是真正必要的,什么是浪费你的时间。

编辑:我正在考虑的另一种方法是创建一个数据类,该类具有基于您可以搜索的各种事物的属性。IE。具有 UPC 等属性的 BoxSearchData 类,然后将其传递给 LocateBox() 并根据为空的属性构建查询。这将帮助您稍后根据多个条件构建搜索。

于 2009-03-25T18:21:57.883 回答
0

在我看来,这似乎没有必要。只需拥有一个具有不同搜索功能的存储库。然后只需在需要时使用您需要的功能。

但是,只有当您拥有将不同类型的搜索排队的工具时,界面部分才会变得有用。然后你可以有一个工厂来创建不同类型的搜索类,这些类都实现了一个接口。此时,您可以枚举排队的搜索类,强制转换为接口,并执行虚拟函数并指向正确的搜索类型。例子:ReturnDataObject GetItem(object param);

附带说明一下,在提取数据时,接口还有其他用途。这只是我想到的第一个例子。

于 2009-03-25T18:28:06.747 回答
0

在此示例中仔细观察时,您会看到只有用于查找的属性发生了变化。当以 OO 方式表示这一点时,您最终会得到一个我称之为“查找”的类(表示搜索,可能是 SQL,也可能是另一种查询语言:一个可以基于某些属性返回 rowId 并搜索到的对象该财产的价值。

真正的行为变化将在查询语言中。所以如果你要创建一个抽象类或接口,它应该服务于那个目的。可以通过在查询调用中添加“属性”参数来区分属性和值变化的问题。

于 2009-03-25T18:47:22.707 回答
0

当您需要大量功能在子类中相同时,抽象类很有用,例如在具有多种可用支付方式的购物车中,您可以有一个定义通用支付方式的抽象类,并让子类继承来自您想要支持的每种实际支付方式(贝宝、信用卡、帐户等)的超类。每个子类的付款授权机制会有所不同,但它们都执行基本相同的功能 - 它们验证用户可以证明他们可以为相关商品或服务付款。

接口有用的一个例子是你有不相关的项目需要以统一的方式提供一些类似的功能。例如,您可能有一个 CMS,其中文章存储在数据库中,但系统将它们缓存到光盘和 HTML 页面,直到数据库中的文章被修改,此时物理文件被删除,直到下一次有人访问数据库中的副本。您的 CMS 可能还支持用户上传图像、PDF 等以存储在光盘上以供访问,但您绝对不希望删除这些文件,因为光盘上的副本代表文件本身,而不是缓存版本。在这种情况下,您可以创建一个 Cacheable 接口,说明缓存到磁盘的类需要实现哪些方法,同时将其留给类本身来实现它们。这更有意义,因为代表不同类型数据的类几乎肯定需要以不同方式实现它们的缓存方案(如果有的话)。

每个允许缓存的类都将被定义为实现 Cacheable 的类,然后您可以在代码中检查这一点。经验不足的编码人员可能会通过获取类并使用大的 switch 语句处理结果来测试他们正在使用的对象的类。这不是正确的方法,因为这意味着您假设某些类对象实现了某些功能,如果您向系统添加一个新类,则需要修改软件中的每个 switch 语句以将其考虑在内。如果你实现了一个接口,你可以测试一个对象是否使用 instanceof 关键字实现了该接口。

if ($thisObject instanceof Cacheable)
{
// Manage item's cache
}

这种方法更好,因为它消除了 switch 语句,从而使您的软件更易于维护。如果您向系统添加一个新类,该类也实现了自己的缓存方案,那么您只需要声明它实现了 Cacheable。由于接口要求所有的类都实现它来声明接口中指定的方法,因此您可以确定任何实现 Cacheable 的类都会提供某些方法供您使用。您的代码不需要知道类如何实现这些方法,只需知道它确实实现了它们。

恐怕这些概念解释起来比实际学习使用要复杂一些,希望我对基本概念的理解足以让您自己弄清楚。

于 2009-04-13T09:49:55.040 回答
0

显然,这里的多态实体是约束。使用字符串是实现相同目的的快速而肮脏的方法,但是您的类型系统完全脱离了循环,垃圾字符串值对于输入的有效性将与有意义的约束规范一样有效。

所以,

LocateBy (Constraint constraint);

abstract class Constraint {
   String toString ();
}

class LocationConstraint extends Constraint { /* ... */}

等等

于 2009-05-05T12:01:37.410 回答