开关箱的设计模式

问题描述 投票:0回答:4

我有一系列开关盒,但似乎有点太复杂了。简化它的最佳方法是什么?我当时正在考虑使用策略设计模式。

我最初的想法是使sendReport成为一个方法,该方法从每个不同的类调用sendReport。但是,我不确定如何实现这一点。谁能给我一些指导,或者关于如何使这种转换案例变得更简单的一些建议。

谢谢。

public static boolean sendReport(AuthToken token, Student client, List<ContactMethod> bestOptions, String data) {
    for (ContactMethod method : bestOptions) {
        switch (method) {
            case TEXT:
                String textMessage = client.getPhoneNumber();
                if (null != textMessage) {
                    TEXT.sendReport(token, client.getFName(), client.getLName(), data, textMessage);
                    return true;
                }
                break;
            case POST:
                String address = client.getAddress();
                String suburb = client.getSuburb();
                String state = client.getState();
                String postcode = client.getPostCode();
                if (null != address && null != suburb &&
                    null != state && null != postcode) {
                    Mail.sendReport(token, client.getFName(), client.getLName(), data, address, suburb, state, postcode);
                    return true;
                }
                break;
            case ELECTRONICMAIL:
                String email = client.getEmailAddress();
                if (null != email) {
                    Email.sendReport(token, client.getFName(), client.getLName(), data, email);
                    return true;
                }
                break;
            case VOICECALL:
                String number = client.getPhoneNumber();
                if (null != number) {
                    PhoneCall.sendReport(token, client.getFName(), client.getLName(), data, number);
                    return true;
                }
                break;
            case FACE_TO_FACE:
                String face2face = client.getFace2Face();
                String personName = client.getPersonName();
                if (null != face2face && null != personName) {
                    Face_To_Face.sendReport(token, client.getFName(), client.getLName(), data, face2face,personName);
                    return true;
                }
                break;
            case MAGIC:
                String magicID = client.getMagic();
                if (null != magicID) {
                    magic.sendReport(token, client.getFName(), client.getLName(), data, magicID);
                    return true;
                }
                break;
            default:
                return false;
        }
    }
    return false;
}
java design-patterns switch-statement simplify
4个回答
2
投票

您甚至不需要设计模式,只需要基本的多态性。

ContactMethod从枚举更改为接口。每个case语句成为接口的实现

public class TextContactMethod implements ContactMethod { ... }    

sendReport变为

for (ContactMethod method : bestOptions) {
    method.fooBar(token, client);
}

1
投票

我只是简单地使开关“阻塞”到方法中并调用它们;例如

public static boolean sendReport(AuthToken token, Student client, 
                                 List<ContactMethod> bestOptions,
                                 String data) {
    for (ContactMethod method : bestOptions) {
        boolean res;
        switch (method) {
            case TEXT:
                res = processText(token, client, data);
                break;
            case POST:
                res = processPost(token, client, data);
                break;
            ...
            default:
                res = false;
        }
        if (res) {
            return true;
        }
    }
    return false;
}

private boolean processText(AuthToken token, Student client) {
    String textMessage = client.getPhoneNumber();
    if (null != textMessage) {
        TEXT.sendReport(token, client.getFName(), client.getLName(), 
                        data, textMessage);
        return true;
    } else {
        return false;
    }
}

当然,您可以使用设计模式来进行修饰,但是简单的过程抽象同样适用。


1
投票

定义具有sendReport方法的公共接口ContactMethod,并为每个实现ContactMethod的开关案例创建不同的实现类。例如;

public static boolean sendReport(AuthToken token, Student client, List<ContactMethod> bestOptions, String data) {
   for (ContactMethod method : bestOptions) {
      if (method.sendReport(token, client, data))
         return true;
   }
}

public class TextContactMethod implements ContactMethod {
    public boolean sendReport(AuthToken token, Student client, String data) {
            String textMessage = client.getPhoneNumber();
            if (null != textMessage) {
                TEXT.sendReport(token, client.getFName(), client.getLName(), data, textMessage);
                return true;
            }
       return false;
    }
}

1
投票

是的,实施策略/政策模式可以完成这项工作。基本上,三个已经存在的答案中有两个显示了该模式的可能实现(Michael's answerAli Gelenler's answer),尽管迈克尔不认为他的实现会遵循模式…

如果一组可能的联系方法是固定的,则您甚至可以将sendReport()添加为枚举的方法,每个枚举实例的实现方式都不同。这为您节省了专用于策略的注册表(并且您无需定义几个不同的类)。

更干净的路径将(如已经提到的答案所建议的那样)定义接口ContactMethod并为您需要的每种联系方式实现该接口。它的优点是您可以轻松添加其他联系方式(特别是如果您使用java.util.ServiceLoader API)。

缺点是,如果联系方法是外部化实体的属性,则需要某种策略的注册表,以及从策略名称到其实现的映射-如前所述,您可以免费获得,当您扩展(滥用?)枚举时。

© www.soinside.com 2019 - 2024. All rights reserved.