Diğer yanıtlar, sorunuzu yanıtlarken bu sorunu yanıtladı. Ama bu fabrika yöntemiyle neyi başarmaya çalıştığınızı anlamak için bir adım geri atmak isterim. Bu fabrika temel olarak IDataSource
parametresine bir veri tipi haritası sunar. Dependency injection daha uygun bir model olabilir, çünkü bu iyi bilinen küçük veri türleri ve uygulamaları kümesidir (örneğinizle belirtildiği gibi). IDataSource<Widget>
uygulayan bir MongoWidgetDataSource
ve IDataSource<Gadget>
uygulayan bir MysqlGadgetDataSource
:
Diyelim ki MySQL tüm Mongo içinde Widgets
ancak tüm Gadgets
saklamak istediğinizi varsayalım
, iki sınıfları olabilir. Bir veri yolu kullanıcısı, bir tüketici yöntemi içinde
MyFactory.getDataSource(Widget.class)
gibi bir fabrika yöntemini kodlamak yerine, uygun
IDataSource
bağımlılığını enjekte ederim.Biz (Mongo'da saklanan) widget'larla şey yapar
MyService
olabilir. Eğer önerildiği üzere bir fabrika kullanarak şu şekilde görünecektir:
public class MyService {
public void doSomething() {
String value = MyFactory.getDataSource(Widget.class).getSomething();
// do something with data returned from the source
}
}
Bunun yerine, hizmete bir yapıcı arg gibi uygun bir veri kaynağını enjekte edilmelidir:
public class MyService {
private final IDataSource<Widget> widgetDataSource;
public MyService(IDataSource<Widget> widgetDataSource) {
this.widgetDataSource = widgetDataSource;
}
public void doSomething() {
String value = widgetDataSource.getSomething();
// now do something with data returned from the source
}
}
Bu yapım yararı vardır senin kod daha tekrar kullanılabilir ve daha kolay birim testi (sahte bağımlılıklar). Eğer MyService
örneğini Sonra
, ayrıca veri kaynaklarını kadar bağlayabilirsiniz. Pek çok proje bu daha kolay, ama onun değil katı bir gereklilik yapmak için (Guice gibi) bağımlılık enjeksiyon çerçeve kullanır. Şahsen olsa, asla biri olmadan herhangi bir gerçek boyutu veya süresi bir proje üzerinde çalışıyoruz.
public static void main(String[] args) {
IDataSource<Widget> widgetDataSource = new MongoWidgetDataSource();
IDataSource<Gadget> gadgetDataSource = new MysqlGadgetDataSource();
MyService service = new MyService(widgetDataSource, gadgetDataSource);
service.doSomething();
}
Guice olarak, böyle bu veri kaynaklarını kadar Tel ediyorum: Eğer bir DI çerçeve kullanmak yoksa arama hizmeti oluştururken
, sadece bağımlılıkları örneğini
public class DataSourceModule extends AbstractModule {
@Override
protected void configure() {
bind(new TypeLiteral<IDataSource<Widget>>() {}).to(MongoWidgetDataSource.class);
bind(new TypeLiteral<IDataSource<Gadget>>() {}).to(MysqlGadgetDataSource.class);
}
}
Bağımlılık inversiyon sorun hakkında düşünmek için farklı bir şekilde biraz, ama çok daha, üretimden bağımsız yeniden kullanılabilir ve sınanabilir kod tabanına yol açabilir.
public static <T> IDataSource<T> getDataSource(MyData dataType) {
System.out.println("Make MyDataSource");
return (IDataSource<T>) new MyDataSource();
}
public static <T> IDataSource<T> getDataSource(MyOtherData dataType) {
System.out.println("Make MyOtherDataSource");
return (IDataSource<T>) new MyOtherDataSource();
}
public void test() {
IDataSource<MyData> myDataSource = getDataSource((MyData) null);
IDataSource<MyOtherData> myOtherDataSource = getDataSource((MyOtherData) null);
}
ben varmış gibi boş tipimiz ziyade döküm null
oluşturmayı tercih edebilir ama bu kalıcı bir tekniktir düşünüyorum:
Bu sorunuza cevap vermez ama güvenle yerine 'equals' ait Class'es' için '==' kullanabilirsiniz. – Boann