嵌套开关或多个功能,什么会更好的设计?

问题描述:

我有,看起来我需要添加一个供应商,我需要的情况下添加到供应商,然后重复method开关这种新的供应商,此嵌套开关或多个功能,什么会更好的设计?

List<Hotel> findAvailHotels(Provider provider, Method method, List<String> codes) { 
    switch (provider) { 
     case PROVIDER_1: 
      //TODO Do common things to provider 1 
      switch (method) { 
       case HOTEL_CODE: 
        break; 
       case DESTINATION_CODE: 
        break; 
       case GEO: 
        break; 
      } 
      break; 
     case PROVIDER_2: 
      switch (method) { 
       case HOTEL_CODE: 
        break; 
       case DESTINATION_CODE: 
        break; 
       case GEO: 
        break; 
      } 
      break; 
    } 

所以每次都像一个大方法。

我从应该被划分成每个method方法老乡的建议,以便例如不是上述情况,这将是

List<Hotel> findAvailHotelsByHotelCode(Provider provider, List<String> codes) { 
    switch (provider) { 
     case PROVIDER_1: 
      //TODO Do common things to provider 1 
      break; 
     case PROVIDER_2: 
      break; 
    } 

List<Hotel> findAvailHotelsByDestinationCode(Provider provider, List<String> codes) { 
    switch (provider) { 
     case PROVIDER_1: 
      //TODO Do common things to provider 1 
      break; 
     case PROVIDER_2: 
      break; 
    } 

List<Hotel> findAvailHotelsByGeo(Provider provider, List<String> codes) { 
    switch (provider) { 
     case PROVIDER_1: 
      //TODO Do common things to provider 1 
      break; 
     case PROVIDER_2: 
      break; 
    } 

个人的想法:也许分成多种方法使得它更加清洁,但如果我需要对PROVIDER_1(尽管method)做一些常见的事情,那么这种常见的事情将需要在每种方法中重复/重复(如上述代码中的//TODO所示),这意味着更多的线代码,但这可能有点不相关。

我想听听一些关于这方面的想法,您认为哪些更具可读性和更干净?任何更好的选择?


编辑:为了让更多的背景,我与酒店供应商工作..大多数供应商具有搜索(hotel_code,DESTINATION_CODE,GEO)的3种常见方法..此方法之外,我可以做一个hotel_code搜索对于所有提供者(通过遍历Provider枚举并调用每个提供者的方法,使用hotel_code枚举参数)..或者我可以将它提供给特定的提供者。

+0

不好,但没有开关语句可行:反射。另一方面,它听起来像你可以通过使用继承来解决这个问题。在基类中收集常见信息并将修改部分放在子类中 – ParkerHalo

+1

@ParkerHalo使用* reflection *应该是在Java中做某件事的最后手段! –

+0

@TimothyTruckle这就是为什么我写了_“不好”_...这也是为什么我没有做出答案,并建议继承/多态 – ParkerHalo

您的问题仍然有点过于抽象,不足以提出“最佳”解决方案,但蒂莫西目前为止是正确的 - 无论哪种情况,您都可以使用多态性。

我建议策略模式,因为您通过使用接口定义广义结构并为每个单一算法(提供者在您的情况下)创建一个专用类。

这至少有两个好处:

  1. 你有一个易于监督的算法名单类的形式。
  2. 您可以通过您的策略对象循环替换外部交换机。

嗯 - 既然你问吧 - 这里是一些示例代码(虽然有点大......)

import java.util.ArrayList; 
import java.util.List; 

public class HotelStuff { 

    private static class Hotel{/* does whatever ...*/} 

    private enum SearchMethod{ 
    HOTELCODE, 
    DESTINATIONCODE, 
    GEOCODE 
    } 

    private interface Providable{ 
    List<Hotel> findAvailHotels(SearchMethod method, List<String> codes); 
    } 

    private static class Provider1 implements Providable{ 
    @Override 
    public List<Hotel> findAvailHotels(SearchMethod method, List<String> codes) { 
     // TODO create the list ... 
     return null; 
    } 
    } 

    public static void main(String[] args) { 
    // TODO Auto-generated method stub 
    List<Providable> providers = new ArrayList<Providable>(); 
    providers.add(new Provider1()); 
    // providers.add(new Provider2 .. and so on  
    List<String> codes = Arrays.asList("123","456"); 
    SearchMethod method = SearchMethod.GEOCODE; 
    List<Hotel> availableHotels = findAvailHotels(providers, method, codes); 
    } 

    public static List<Hotel> findAvailHotels(List<Providable> providers, SearchMethod method, List<String> codes) { 
    List<Hotel> result = new ArrayList<Hotel>(); 
    List<Hotel> partResult; 
    for(Providable provider: providers) { 
     partResult = provider.findAvailHotels(method, codes); 
     result.addAll(partResult); 
    } 
    return result; 
    } 

} 

当然你应该实现在单独的文件中的类 - 我只是把它们整合到一个文件中以缩短它。

+0

我编辑了上面的代码,并添加更多的上下文,使其更清晰 – prettyvoid

+0

那么那就是那个。因为你的“findAvailHotels ...”方法已经有了相同的签名,你可以用方法参数将所有三个方法联合为一个方法,并将它作为接口的一部分。 – ospf

+0

当你得到时间时,你会善意举一个简单的例子吗?因为这会让我更清楚地理解。谢谢 – prettyvoid

除非你switch语句是在工厂你应该更好地利用多态性

你应该看看访问者模式和双重调度。

*访问者定义为:

表示待上的对象结构的元素执行的操作。访问者可以让你定义一个新的操作而不需要改变它所操作的元素的类。

在你的情况提供商是对象,而方法是操作。

在计算的选择取决于参数的运行时类型的情况下,双重调度非常有用。在你的情况下:你想根据供应商方法的类型做些什么。