2015-05-19 9 views
6

farklı jenerik parametrenin soyut sınıf içindeki bir jenerik dönmek mi Bazı satırları (yani tüm tablo) döndürecek bir yöntem yapmak istiyorum, ancak etki alanı sınıfları yerine, ilgili model sınıflarını (temelde etki alanıyla aynıdır, ancak ilişki listesi ve diğer bazı şeyler olmadan) döndürmek istiyorum. sunum katmanı için gerek yok).kötü uygulama Şimdi</p> <p>(silme, vb satırları, insert getirme) Ben veritabanı işlemleri uygulamak bazı yöntemler tanımladık bu soyut sınıf var

soyut sınıf

public abstract class DomainService<T extends Domain> { 

    protected abstract Logger getLogger(); 

    protected final Validator validator; 

    protected DomainService() { 
     ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); 
     this.validator = factory.getValidator(); 
    } 

    abstract public void insert(T object) throws ValidationException; 

    abstract public void delete(T object) throws EntityNotFoundException; 

    abstract public List<T> fetchAll(); 
} 

ve ben fetchAll() arayıp sonra her bir öğeyi yineleme ve model eşdeğer oluşturmak ve liste olduğunu dönecektir başka bir yöntemi eklemek istiyorum.

public <K extends Model> List<K> fetchAllModels(Class<K> modelClass) { 
     List<T> domains = fetchAll(); 
     List<K> models = new ArrayList<K>(domains.size()); 

     for (T domain : domains) { 
      K model = modelClass.newInstance(); 
      models.add(model.fillIn(domain)); 
     } 

     return models; 
    } 

bu kod sadece şimdi soru yazma gerçi olduğunu göz ardı ederek, bu kabul edilebilir sınıfında tanımlı olmadığı genel bir parametre eklemektir. IMO bir sınıf diğer veri türlerini döndüren yöntemlere sahip olabilir, bu yüzden bir sorun olmamalıdır. Benim durumumda sınıfı geçiyorum, böylece modelin bir örneğini oluşturabilir ve daha sonra üyeleri doldurmak için alanı kullanabilirim. Ben

  • manken sınıfına bir yöntemi ekleyin Yazdığım bir o alanı nesneden kendini oluşturmak için, iki görüş oldu. Etki alanı nesnesini argüman olarak alan bir kurucu düşünmekteydim, ama sanırım jenerik kullanarak bir kurucuyu çağırmak biraz güçlük çekiyor (En azından yansıma yardımcı programlarına ihtiyaç duyacaktır). varsayılan yapıcıyı kullanarak bir örnek oluşturduktan sonra ayrıntıları. Ayrıca, model daha yüksek bir katmandadır ve daha yüksek katmanların daha düşük değerleri kullanması gerektiğini düşünüyorum (Veritabanı-> Etki Alanı sınıfları-> Erişim sınıfları (DAO) -> Hizmet sınıfları-> Servlet sınıfları ----> JSP verileri gösterir)

  • Ben onun modeline etki alanını dönüştüren alanı sınıfına bir yöntemi ekleyin ve modeline

    public <K> List<K> fetchAllModels() { 
        List<T> domains = fetchAll(); 
        List<K> models = new ArrayList<K>(domains.size()); 
    
        for (T domain : domains) { 
         models.add(domain.createModel()); 
        } 
    
        return models; 
    } 
    

sınıfını geçmek zorunda kalmadan böyle hitap ama etki alanı sınıfı olarak olması gerektiğini hissediyordu Veritabanındaki tablonun bir temsilini, sütunlarla ilgisi olan tek yöntemle temizleyin.

Parametreyi sınıfa eklemek daha iyi olur muydu? Sadece

Herhangi bir düşünce yorumlar her zaman

+0

Seni aldığımdan emin değilim, ama evet; Yalnızca tek bir yöntem için gerekli olan tip parametrelerine sahipseniz; o zaman bunu gerçekten yapmalısınız - bunu sınıfsal bir parametre yapmaya gerek yoktur. – GhostCat

+1

Yanılıyorsam düzeltin, ama B seçeneği, tür çıkarımından dolayı işe yaramazsa, Java derleyicisi _T_ türünde yalnızca _T_ türünde bilgi nasıl yazabilir? – superbob

+0

Yukarıdakileri göz ardı ederek, soruları karıştırdım. K, temel soyut sınıf olan Modeli genişletir. Ve # createModel etki alanı, model türünü döndürür. –

cevap

4

hoşgeldin ... Bu yöntem için kullanmak için gidiyorum kabul edilebilir sınıfında tanımlı olmadığı genel bir parametre eklemektir

Kesinlikle. Her zaman bitti.

Modelinizi yönteme geçirerek ilk çözümünüzü tercih ederim.

Ancak, gerçekten istediğiniz şey, T.'den K'yi yaratan bir işlevdir. Java8'de, bu çok kısa bir sürede yapılabilir.

public <K extends Model> List<K> fetchAllModels(Function<T,K> func) { 
... 
      K model = func.apply(domain); 

ve func (veya en azından öyle görünüyor) gibi yapıcı geçebilir

public M(D domain) // constructor 

etki alanının 'D'

service.fectchAllModels(M::new) 

için Model 'M' söylüyorlar Eğer Stream kullanırsanız

, fetchAllModels() çok daha basit hale gelir

abstract public Stream<T> fetchAll(); 

public <K extends Model> Stream<K> fetchAllModels(Function<T,K> func) { 
    return fetchAll().map(func) 
} 

Ve sonra, neden biz bile bu yöntemi gerekiyor? Sadece

// fetch domains, convert each to M 
Stream<M> models = service.fetchAll().map(M::new); 

yapmak yüzden fetchAllModels() kaldırmak ve etki alanından modeline herhangi bağımlılıkları kaldırabilirsiniz.

+0

Teşekkür ederim. Java 7 kullanıyorum ama bunu aklımda tutacağım –

İlgili konular