2015-01-28 17 views
6

Soyut bir java sınıfına "BaseOperation" var. BaseOperation aitHem değişken dönüş türü hem de değişken giriş bağımsız değişkenlerine sahip bir java yöntemi

public abstract T execute() 
{ 
    ... 

    return T; 
} 

Altsınıflar bu yöntemi uygulamak gerekir: Bu sınıf yalnızca tek soyut yöntem vardır,

public class GetUsersOperation extends BaseOperation<GetUsersResponse> 
{ 
    ... 

    @Override 
    public GetUsersResponse execute() 
    { 

     ... 

     return GetUsersResponse; 
    } 

} 

Bu BaseOperation sınıftaki tüm ortak "operasyon" mantığı koymak için harika bir yoldur ancak hala her beton alt sınıfın execute() yönteminin farklı bir dönüş türüne sahip olması gerekir.

Şimdi execute() yöntemlerinin değişken miktarda argümanlara sahip olmasını sağlamak için bu yapıyı değiştirmem gerekiyor.

execute(String, int) 

ve başka gerekir: Örneğin bir somut alt sınıf gerektirecektir Bu zordur

execute(Date, Date, String) 

, yürütme yöntemi temel sınıfta bildirildiği için. Sadece tabandaki yürütme yöntemlerini aşırı yüklemek ideal değildir. İlk olarak, aşırı yükleme miktarı çok büyük olurdu. İkincisi, her alt sınıf sadece yürütme yöntemlerinden birini kullanacak, diğerlerinin noktası nedir? Bu önemli 2'sine sahiptir Açıkçası

execute(Object... arguments) 
{ 
    String s = (String) arguments[0]; 
    ... 
} 

:

execute(Object... arguments) 

Sonra alt sınıflara tüm argümanları downcast:

(Bence) en kolay çözüm varargs ile yürütmek yöntem bildirmek için olurdu downsides:

  • Tüm tüm yayınlama işlemleri nedeniyle azaltılmış performans
  • execute() yöntemlerini arama, artık herhangi bir nesne miktarı witout derleyici uyarılarını iletilebileceğinden, kesinlikle yazılmaz.

Bu dezavantajları olmayan desen veya başka çözümler var mı?

cevap

2

Daha önce de belirttiğimiz gibi, sorununuzu çözmek için ortak yaklaşım, fasulye tutma parametrelerini kullanmaktır.Böyle

public interface BaseOperation<T> { 
    public T execute(); 
} 

public class AddOperation implements BaseOperation<Integer> { 
    private int a, b; 

    public void setA(int arg){ 
    a = arg ; 
    return this; 
    } 

    public void setB(int arg){ 
    b = arg; 
    return this; 
    } 

    @Override 
    public Integer execute() { 
    return a+b ; 
    } 
} 

Sonra kullanmak: Ama burada bir inşaatçı yaklaşımına dayalı, başka çözüm

new AddOperation().setA(1).setB(2).execute(); 

Gerekli ve bu şekilde isteğe bağlı parametreler mix yapabilirsiniz:

public class MultipleAddOperation implements BaseOperation<Integer> { 
    private int sum ; 

    public MultipleAddOperation(int requiredInt){ 
    sum = requiredInt; 
    } 

    public void add(int optionalInt){ 
    sum += optionalInt ; 
    return this; 
    } 

    @Override 
    public Integer execute(){ 
    return sum; 
    } 
} 

Ve benzeri:

new MultipleAddOperation(5).add(1).add(2).execute(); 
+0

Gerekli girdi ile ilgili mantığın, ayrı bir fasülye sınıfı yerine, alt sınıfın öznitelikleri (alanlar) olarak kodlanmasını seviyorum. Bununla birlikte, uygun parametreleri ayarlamadan çalıştırmayı() çağırmamı engelleyen hiçbir şey yoktur. Bu çözülebilir mi? – user1884155

+0

@ user1884155 Evet, işlem yapıcıdaki bağımsız değişkeni geçerek, benim düzenime bakın;) – NiziL

+0

Ah, açıkçası. Bu çözümü 'basit' javabean çözümü üzerinde tercih ediyorum çünkü tüm parametrelerim gerekli ve yaptığım her işlem sınıfı için ek bir fasulye sınıfı sunmak istemiyorum. Teşekkürler! – user1884155

5

Parametreleri tutan bir fasulye kullanabilirsiniz:

public interface BaseOperation<T, U> { 
    T execute(U input); 
} 

public class GetUsersOperation implements BaseOperation<GetUsersResponse, UserInput> { 

    @Override 
    public GetUsersResponse execute(UserInput input) { 
     Date date = input.getDate(); 
     return new GetUsersResponse(date); 
    } 

} 

Sizin soyut sınıf yalnızca tek bir soyut yöntem vardır: daha iyi bir arayüz kullanın. Sadece bir sınıfı genişletirken birkaç arabirim uygulayabilirsiniz.

+0

Teşekkür ederiz ompt yanıtı. Temel sınıfım başka yöntemlere sahip, ancak yalnızca 1 PUBLIC yöntemine sahip. Diğer tüm özel/korumalı yöntemler soyut değildir ve mesajlaşma, mesaj ayrıştırma vb. Gibi ortak çalışmaları yapar. Arayüzlerin java 1.7'de gerçek kodu olamaz, bu yüzden bir ara yüze dönüştürmenin mümkün olmadığını düşünüyorum. Yoksa bu konuda yanlış mıyım? – user1884155

+0

@ user1884155 Hayır, haklısınız, sadece tek bir soyut yöntemin olduğunu düşündüm. – sp00m

+1

Birden fazla kurucuya sahip bir sınıftan ziyade, bir fasulyeyi neden tercih edeceğine meraklı mısınız? Aşırı yüklü kurucular ile paramları ayarlayan tüm ekstra hatları önleyebilir ve ayrıca kabul edilebilir parametre kombinasyonları ve gerekli değerler hakkında bazı bilgiler sağlayabilirsiniz. – Blegger

İlgili konular