2016-08-01 10 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の経験から、抽象クラス/インターフェースを使用して、私が与えられる具体的なタイプがわからないときに対処しました。ここでは、具体的な型を抽象ファクトリコンストラクタに直ちに割り当てるようです。私の2番目の質問はこのインスタンスにあると思います。すべてのメソッドシグネチャを繰り返すのではなく、ここで直接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では、すべてのクラスも自動的にインターフェイスされます。実際にはクラスのインスタンスを作成しているため、 'newing up' - 'インターフェース'のインスタンスを作成することについては何も変わりありません。

いくつかの抽象クラスの目的は、具体的にはインターフェースを定義することですが、それ自体の「デフォルト実装」を返すファクトリコンストラクタを持っています。例えば

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

動作するようです。

関連する問題