Java - 概括不同的类,类似的方法(不改变子类?)

时间:2016-07-22 23:33:15

标签: java generics composition

不确定这是否可行,但我遇到两个接口具有相同方法的情况。这些是给出的接口,所以我无法改变它们。

给定接口

interface SomeGivenService {
    boolean authenticate(String username, String password);
    Object someSpecialMethod(Object param);
}

interface AnotherGivenService {
    boolean authenticate(String username, String password);
    String aGreatMethod();
    String sayHello();
}

为了使用这项服务,我创建了一个类,并在此服务抛出错误时进行了一些处理。

class SomeGivenServiceConsumer {

    SomeGivenService a;

    public SomeGivenServiceConsumer(SomeGivenService a) {
        this.a = a;
    }

    public authenticate(MyUserPassBean bean) {
        try {
            a.authenticate(bean.username, bean.password);
        } catch (Exception e) {
            throw new MyException();
        }
        ...
    }
}

class AnotherGivenServiceConsumer {

    AnotherGivenService a;

    public AnotherGivenServiceConsumer(AnotherGivenService a) {
        this.a = a;
    }

    public authenticate(MyUserPassBean bean) {
        try {
            a.authenticate(bean.username, bean.password);
        } catch (Exception e) {
            throw new MyException();
        }
        ...
    }
}

我的消费者可以避免这种代码重复吗?我可能会有很多,并希望避免这些重复的代码。 我最初想过更改我的使用者以接收实现此身份验证的接口,但由于我无法更改给定的接口,因此不确定这是否可行。

是否可以拥有一个具有方法的"通用接口?"或使用一些设计模式?有任何想法吗? 我在尝试什么:

class AnotherGivenServiceConsumer {

    AnotherGivenService a;
    GivenServiceAuthenticable b;

    public AnotherGivenServiceConsumer(AnotherGivenService a, 
                                       GivenServiceAuthenticable b) {
        this.a = a;
        this.b = b;
    }

    public authenticate(MyUserPassBean bean) throws MyException {
        return b.authenticate(bean.username, bean.password);
    }
}

interface GivenServiceAuthenticable<T> {
    boolean authenticate(T givenService, MyUserPassBean bean);
}

class GivenServiceAuthenticableImpl<T> implements GivenServiceAuthenticable<T> {
    boolean authenticate(T givenService, MyUserPassBean bean) {
        try {
            //this won't compile as it's a generic class..
            t.authenticate(bean.username, bean.password); 
        } catch (Exception e) {
            throw new MyException();
        }
        ...
    }
}

其他问题是如果我不能更改它以实现我的新对象,如何实例化这个对象?

2 个答案:

答案 0 :(得分:1)

您可以使用template pattern在基类中实现常用功能,同时将单个变化行委托给子类:

abstract class ConsumerBase {
    public void authenticate(MyUserPassBean bean) {
        try {
            authenticate(bean.username, bean.password);
        } catch (Exception e) {
            throw new MyException();
        }
        //...
    }

    protected abstract boolean authenticate(String username, String password);
}

class SomeGivenServiceConsumer extends ConsumerBase {

    SomeGivenService a;

    public SomeGivenServiceConsumer(SomeGivenService a) {
        this.a = a;
    }

    @Override
    protected boolean authenticate(String username, String password) {
        return a.authenticate(username, password);
    }
}

class AnotherGivenServiceConsumer extends ConsumerBase {

    AnotherGivenService a;

    public AnotherGivenServiceConsumer(AnotherGivenService a) {
        this.a = a;
    }

    @Override
    protected boolean authenticate(String username, String password) {
        return a.authenticate(username, password);
    }
}

答案 1 :(得分:0)

您需要做的是使用继承。然后处理超类中的错误,即

    class SomeGivenServiceConsumer {

        SomeGivenService a;
        AnotherGivenService b;

        public SomeGivenServiceConsumer(SomeGivenService a) {
            this.a = a;
            try{
             authenticate(MyUserPassBean);
            }catch (Exception e) {
            System.out.println("Thrown exception has been caught : "+e.getMessage());
            }
        }

        public authenticate(MyUserPassBean bean) throws MyException {
                //your implementation here
        }
    }    
    class AnotherGivenServiceConsumer extends SomeGivenServiceConsumer{

        public AnotherGivenServiceConsumer(AnotherGivenService b) {
            super(someGivenService);//construct superclass
            authenticate(MyUserPassBean);//call subclass authenticate method
        }

        @override
        public authenticate(MyUserPassBean bean) throws MyException {
                super.authenticate(MyUserPassBean);//call superclass method
                //your implementation here

        }
    }

然后构建子类:

public static void main(String[] args) {
    new AnotherGivenServiceConsumer(AnotherGivenService);
}