2016-08-01 75 views
2

我最近遇到了一些使用抽象類作爲接口的例子,但也將工廠構造函數添加到抽象接口,因此它可以在某種意義上被「新」化。例如:帶工廠構造函數的抽象類的好處?

這項服務的
abstract class WidgetService { 
    factory WidgetService() = ConcreteWidgetService; 

    Widget getWidget(); 
    void saveWidget(Widget widget); 
} 

class ConcreteWidgetService extends BaseWidgetService implements WidgetService { 

    WidgetService(); 

    Widget getWidget() { 
     // code to get widget here 
    } 

    void saveWidget(Widget widget) { 
     // code to save widget here 
    } 
} 

用法將在其他一些服務或組件,像這樣:

WidgetService _service = new WidgetService(); 

根據我的這個樣本的理解,線以上將基本上是「新」了WidgetService通常會產生來自Dart分析器的警告,並且根據將ConcreateWidgetService分配給WidgetService的工廠構造函數,該服務變量實際上將是ConcreateWidgetService的一個實例。

這種方法有什麼好處嗎?從我的OOP經驗來看,當我不知道具體類型時,我使用抽象類/接口來編程。在這裏,我們似乎將具體類型立即分配給抽象工廠構造函數。我想我的第二個問題是在這個例子中,爲什麼不直接在這裏使用ConcreteWidgetService而不是重複所有的方法簽名?

回答

2

在你的例子中,好處是有限的,但在更復雜的情況下,好處變得更加清晰。

工廠構造函數允許您更多地控制構造函數返回的內容。它可以返回一個子類的實例或已經存在的(緩存的)實例。

它可以返回基於構造函數的參數不同的具體實現:

abstract class WidgetService { 
    WidgetService _cached; 
    factory WidgetService(String type) { 
     switch(type) { 
     case 'a': return new ConcreteWidgetServiceA(); 
     case 'b': return new ConcreteWidgetServiceA(); 
     default: return _cached ??= new DummyWidgetServiceA(); 
     } 
    } 
    Widget getWidget(); 
    void saveWidget(Widget widget); 
} 

你的例子似乎被製備成最終擴展到這種更靈活的方式。

2

在Dart中,所有類都是自動接口。創建一個實例 - '新興' - '接口'並不奇怪,因爲它實際上只是創建一個類的實例。

一些抽象類的目的是專門定義一個接口,但他們有工廠構造函數返回自己的「默認實現」。

例如:

void main() { 
    var v = new Map(); 
    print(v.runtimeType); 
} 

打印:_InternalLinkedHashMap - 的Map(當前)默認實現。

核心庫用戶可以創建並使用Map的實例,而無需知道或關心他們實際獲得的實現。庫作者可能會更改實現而不會破壞任何人的代碼。

當然,其他類也可以實現Map

關於您的代碼示例,WidgetService _service = new WidgetService();不會生成分析器警告。看到這個example on DartPad(注意我在你的示例中修正了一些錯誤)。

factory WidgetService() = ConcreteWidgetService; 

代替:

我最初是困惑

factory WidgetService() => new ConcreteWidgetService(); 

,但它似乎工作。