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

时间:2017-09-26 08:58:05

标签: java oop design-patterns switch-statement

我有一个看起来像这样的大方法

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开关。

我得到了一位研究员的建议,应该将其分成每个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所示),这意味着更多的代码行,但这可能有点无关紧要。

我想听听一些关于此问题的想法,您认为哪个更具可读性和更干净?还有更好的选择吗?

编辑:为了提供更多背景信息,我与酒店提供商合作..大多数提供商都有3种常见的搜索方法(hotel_code,destination_code,geo)..从这个方法之外我可以做{ {1}}搜索所有提供者(通过循环提供者枚举并使用hotel_code枚举参数调用每个提供者的方法)..或者我可以将其用于特定提供者。

3 个答案:

答案 0 :(得分:2)

你的问题仍然有点过于抽象,无法提出“最佳”解决方案,但提摩太到目前为止是正确的 - 在任何一种情况下你都可以使用polimorphism。

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

这至少有两个好处:

  1. 您可以通过类的形式轻松监督算法列表。
  2. 您可以通过策略对象循环替换外部开关。
  3. 嗯 - 既然你要求它 - 这里有一些示例代码(虽然有点大......)

    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;
      }
    
    }
    

    当然你应该在单独的文件中实现这些类 - 我只是把它们放在一个文件中来缩短它。

答案 1 :(得分:1)

除非您的switch声明位于工厂中,否则最好使用多态

答案 2 :(得分:0)

您应该同时查看访客模式和双重调度。

四人帮将访客定义为:

  

表示要对对象结构的元素执行的操作。访问者允许您定义新操作,而无需更改其操作的元素的类。

在您的情况下, Provider 是对象,而 Method 就是操作。

在计算选择取决于其参数的运行时类型的情况下,双重调度很有用。在您的情况下:您希望根据提供程序方法的类型执行某些操作。