这是一个非常通用的“最佳做法”问题,但这是一个例子。
假设我有一部电影编目应用。我想让我的用户有机会为IMDb或Metacritic指定其概要/评级信息。
我这样做:
if (preferredSupplier == "imdb"){
getIMDbRating(movieName);
}else{
getMetacriticRating(movieName);
}
或者这个:
getRating(movieName, preferredSupplier);
我更喜欢第二个,但这意味着函数必须遵循非常不同的逻辑,具体取决于第二个参数的值(例如,Metacritic可能需要屏幕抓取,其中IMDb可能有一个很好的API)。 / p>
或者我应该将它们结合起来?因为在getRating()中充当包装函数,并根据第二个参数的值调用getIMDbRating()或getMetacriticRating()。
答案 0 :(得分:6)
第二个允许您随着时间的推移扩展首选供应商的数量,您仍然可以(内部)将这些作为两个单独的方法来实现。
如果这是我,我会看两个类(Imdb和Metacritic),它们都来自RatingProvider基类,并以不同方式实现getRating。
或者,如果我开始使用我的模板,我会看着Bridge模式。
只有你知道你的系统可能发生的变化,所以你知道你是否需要去城里,但是你可以通过一个API,你可以以统一的方式获得评分,无论他们实际来自哪里,我,是一个比你必须通过选择一种方法或另一种方法做出决定的更好的API。
答案 1 :(得分:4)
使用getRating方法获得RatingProvider类可能是个好主意。
您可以将不同的评级提供程序作为其子类,这些提供程序将自己实现如何获取/处理评级。
答案 2 :(得分:1)
两种解决方案都不理想。你真正应该做的是使用GetRating(字符串moviename)函数将preferredSupplier实现为接口或抽象类。
然后为类IMDBSupplier和MetaCriticSupplier实现接口,并让每个类都有自己的逻辑来获得评级。这使得getRating()函数完全独立于消耗它的任何代码,这是一种良好的,松散耦合的设计。
在您的类中消耗供应商,它并不关心它是哪种类型 - 它只是调用GetRating()。 GetRating()与供应商无关。
答案 3 :(得分:1)
我将使用名为getRating的抽象方法定义一个名为MovieDatabase的抽象类,然后提供为各种提供程序实现getRating方法的子类(如IMDb,Metacritic)。
通过此设置,您可以编写与提供程序无关的代码,即对特定提供程序一无所知。它只需要一个MovieDatabase实例并在其上调用getRating操作,而不必担心提供者或实现细节。
这种方法的优点是它更具可扩展性。如果要添加更多提供程序或操作,可以在一个位置(MovieDatabase类及其子类)执行此操作,其余代码应该可以正常工作。
答案 4 :(得分:0)
我会把它们结合起来。正如您所说,这两者可能需要完全不同的实现,并且将实现代码分成不同的函数,使事物更易读,更易于维护。但是拥有一个呼叫点也很不错。您可以考虑将其放在一个类中,将实现函数标记为私有,将包装器标记为public。这样包装器是唯一的接触点。通过明确表示包装器是这些函数的单个调用点,它将进一步提高可维护性。
答案 5 :(得分:0)
我的偏好是你最后的想法:同时使用两者。拥有一个以源为参数的功能,可以很容易地编写大量代码,通过简单的值更改(可能来自UI)从供应商切换到供应商。如果/当您打算与固定的已知供应商联系时,您还可以使用方便的单供应商功能进行呼叫。
答案 6 :(得分:0)
第二个选项是最好的(在TO中它是名为Factory的b.e.t.w.e.e.n)。给它一个默认行为,并在其中为每个提供者调用一个不同的函数,在所有那些ifsp>中没有任何一点
答案 7 :(得分:0)
我认为这取决于您使用方法的频率,代码的位置和方式。请记住,编写例程的主要原因是它们是 - 这是正确的 - 例程。也就是说,例程应包含您希望重用的代码,并且应该以易于重用的方式编写。
有了这个说,如果我面对你的例子(并且用C#编码),我可能最终会为不同类型的db搜索创建一个enum
,然后有一个包装方法接受这样的{ {1}}作为参数,并从包装器方法调用不同的数据收集方法 - 类似于您在帖子末尾建议的内容,但不是字符串作为输入。
答案 8 :(得分:0)
难道不会取决于您使用它的频率吗?如果您在整个代码中反复进行基本检查,那么函数将避免重复该代码块。
但是,如果你在这里和那里只使用那个逻辑几次,那么第一种方式可能更清楚。
答案 9 :(得分:0)
如果你的函数返回相同类型的响应,那么在单个函数中重载是有意义的。
如果你的函数根据输入返回非常不同的东西,你应该使用两个函数来区分它们返回不同的东西。
例如,如果IMDB评级为5星级,而Metacritic评级为4星级,您需要明确表示应该以不同方式处理它们。
使用单独的类将有助于澄清,而不是将所有这些功能都放在那里。
答案 10 :(得分:0)
为什么你不能做像
这样的事情public interface IRating{
public Rating getRating();
}
public IMDBRating extends Rating
public MetacriticRating extends Rating