在Java中分离方法调用接口实现,也许使用Spring

时间:2013-11-16 12:56:52

标签: java spring interface

我有这样的界面:

public interface ISmsService {
    //method for vendor A
    String sendSms();

    //method for vendorB
    int sendSms(String loginid);
}

该接口描述了两个供应商的重载方法。

我有一个像这样的供应商实现:

public class VendorAService implements ISmsService{

    @Override
    public String sendSms() {
        return "send msg via vendor A";
    }

    //I want to restrict the usage of this method for vendor B instance at compile time
    @Override
    public int sendSms(String loginid) {
        //I can throw an exception but I do not want to restrict it at runtime.
        return 0;
    }

}

这样的供应商B实现:

public class VendorBService implements ISmsService{

    //I want to restrict the usage of this method for vendor A instance at compile time
    @Override
    public String sendSms() {
        //I can throw an exception but I do not want to restrict it at runtime
        return null;
    }

    @Override
    public int sendSms(String loginid) {
        return 1000;
    }

}

我的实施者课程是这样的:

public class User {


    public static void main(String[] args) {
        ISmsService smsService = new VendorAService();
        smsService.sendSms("12345"); // I want thiş line gives a compile time error. I want only a vendorB type can call this method.

        smsService = new VendorBService();
        smsService.sendSms(); //Same here. I just want vendorA type can call sendSms method without a String parameter
    }

}

正如我在评论行中描述的那样,我想指定一个供应商实例只能调用一个特定的方法。我可以在运行时抛出错误的供应商调用之类的异常。但是如果有可能我想在编译时限制行为。

有人遇到过这种问题吗?

春天有解决方法吗?

提前致谢

3 个答案:

答案 0 :(得分:4)

如果您不希望用户能够调用错误的方法,并且您希望编译器为您进行检查,则解决方案非常简单:完全删除接口ISmsService。在您的情况下,它根本没有帮助,引入偶然的复杂性,而不提供任何简化作为回报。接口的用户需要在供应商之间保持差异化,即使他们提供了一个可以消除差异的接口。

如果你想获得界面的好处,你应该以某种方式统一这两种方法,让用户调用接口方法,而不用考虑后面的哪个供应商。例如,您可以这样做:

class SmsParameters {
    ... // Add methods to set parameters, in some non-restrictive way.
    ... // In particular, users should be able to pass login parameters through it
}

class SmsReturn {
    ... // Add methods to harvest the return value, e.g. as an Object
}

interface ISmsService {
     SmsReturn sendSms(SmsParameters args);
}

编译器可以在将供应商与呼叫者匹配方面做得不多,但至少调用者只能调用一种方法。

答案 1 :(得分:1)

接口应分为两个不同的接口,每个接口包含一个方法。第一个类应该只实现第一个接口,第二个类应该只实现第二个接口。

答案 2 :(得分:1)

我建议改变这样的界面

public interface ISmsService {

    // Common method, with optional parameter
    Object sendSms(String...loginid);

}

然后实现可能是

public class VendorAService implements ISmsService{

    @Override
    public Object sendSms(Strong...loginid) {

        // here you can use the parameter          

        return "send msg via vendor A";
    }
}

public class VendorBService implements ISmsService{

    @Override
    public Object sendSms(Strong...loginid) {

        // here you can ignore the parameter

        return 1000;
    }
}

由于参数是可选的,因此可以使用

    ISmsService smsService = new VendorAService();
    smsService.sendSms("12345"); 

    smsService = new VendorBService();
    smsService.sendSms();                    
    smsService.sendSms("random-string");     // not important but, this would work without causing any problems