2016-07-22 23 views
3

不知道這是否可能,但我有兩種接口具有相同方法的情況。這些是給定的接口,所以我不能改變它們。Java - 概括不同的類,類似的方法(不更改子類?)

鑑於接口

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(); 
     } 
     ... 
    } 
} 

另一個問題是如何實例化這個對象,如果我不能改變它來實現我的新對象?

+0

您的'authenticate'方法缺少返回類型。 – shmosel

+0

你有很多這些服務,或只是很多消費者? – shmosel

+0

實現給定接口的所有類是否具有完全相同的認證邏輯?如果是的話,你可以簡單地引入一個新的「接口」來擴展給定的接口,讓你的Consumer使用'authenticate(user,password)'方法的單一定義實現這個接口。 – CKing

回答

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); 
    } 
} 
+0

你忘了擴展'ConsumerBase';此外,只有當GivenService和AnotherGivenService實現具有不同的方式/邏輯來驗證用戶時,這纔有意義。如果他們有完全相同的代碼/邏輯來驗證用戶,這將是一個矯枉過正。 – CKing

+0

humm,這很有道理@shosel ..這就是我要找的!謝謝!! CKing,他們有幾乎相同的邏輯..唯一的變化就是每個'Consumer'從一個特定的對象調用'authenticate' ..所以我相信實現這個的唯一方法就是使用這個'abstract'方法..謝謝!! –

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); 
} 
+0

'AnotherGivenServiceConsumer'不能擴展'SomeGivenServiceConsumer',因爲它們除了認證之外還有其他不同的方法..但是假設你的意思是一個'BaseConsumer',你的想法與shmosel提出的類似,除了我更喜歡他的,因爲我仍然不喜歡'不需要在構造函數上調用'authenticate' ..但非常感謝您的幫助! –

相關問題