2016-11-07 8 views
2

ここでは、n個のリーフとブランチを持つメニュービルダーをビルドしています。ビルダーのリファレンスを正しく返さないため、問題が生じません。ここでネストされたメニュービルダーは、Cで終わることはありません。

コード

public interface IMenuBuilder 
{ 
    IMenuBuilder AddLeaf(string name); 
    ISubMenuBuilder AddBranch(string name); 
    void Build(); 
} 

public interface ISubMenuBuilder : IMenuBuilder 
{ 
    ISubMenuBuilder AddLeaf(string name); 
    INestSubMenuBuilder AddBranch(string name); 
    IMenuBuilder Build(); 
} 

public interface INestSubMenuBuilder : ISubMenuBuilder 
{ 
    INestSubMenuBuilder AddLeaf(string name); 
    INestSubMenuBuilder AddBranch(string name); 
    ISubMenuBuilder Build(); 
} 

public class MenuBuilder : IMenuBuilder 
{ 
    List<Menu> menus = new List<Menu>(); 
    public IMenuBuilder AddLeaf(string name) 
    { 
     var menu = new RootMenu { Name = name }; 
     menus.Add(menu); 
     return this; 
    } 

    public ISubMenuBuilder AddBranch(string name) 
    { 
     var menu = new RootMenu { Name = name }; 
     menus.Add(menu); 
     return new SubMenuBuilder(this, menu); 
    } 

    public void Build() 
    { 
    } 
} 

public class SubMenuBuilder : ISubMenuBuilder 
{ 
    private IMenuBuilder menuBuilder; 
    private ISubMenuHolder menu; 

    public SubMenuBuilder(IMenuBuilder menuBuilder, ISubMenuHolder menu) 
    { 
     this.menuBuilder = menuBuilder; 
     this.menu = menu; 
    } 

    protected SubMenuBuilder(ISubMenuHolder menu) 
    { 
     this.menu = menu; 
    } 

    public ISubMenuBuilder AddLeaf(string name) 
    { 
     var leafMenu = new LeafMenu { Name = name }; 
     leafMenu.ParentId = (leafMenu as Menu).Id; 
     menu.AddSubMenu(leafMenu); 
     return this; 
    } 

    public INestSubMenuBuilder AddBranch(string name) 
    { 
     var branchMenu = new BranchMenu { Name = name }; 
     branchMenu.ParentId = (branchMenu as Menu).Id; 
     menu.AddSubMenu(branchMenu); 
     return new NestSubMenuBuilder(this, branchMenu); 
    } 

    public IMenuBuilder Build() 
    { 
     return menuBuilder; 
    } 


    IMenuBuilder IMenuBuilder.AddLeaf(string name) 
    { 
     this.AddLeaf(name); 
     return this; 
    } 

    ISubMenuBuilder IMenuBuilder.AddBranch(string name) 
    { 
     this.AddBranch(name); 
     return this; 
    } 

    void IMenuBuilder.Build() 
    { 
    } 
} 

public class NestSubMenuBuilder : INestSubMenuBuilder 
{ 
    private ISubMenuBuilder subMenuBuilder; 
    private ISubMenuHolder branchMenu; 

    public NestSubMenuBuilder(ISubMenuBuilder subMenuBuilder, ISubMenuHolder branchMenu) 
    { 
     this.subMenuBuilder = subMenuBuilder; 
     this.branchMenu = branchMenu; 
    } 

    public INestSubMenuBuilder AddLeaf(string name) 
    { 
     var leafMenu = new LeafMenu { Name = name }; 
     leafMenu.ParentId = (leafMenu as Menu).Id; 
     branchMenu.AddSubMenu(leafMenu); 
     return this; 
    } 

    public ISubMenuBuilder Build() 
    { 
     return subMenuBuilder; 
    } 

    public INestSubMenuBuilder AddBranch(string name) 
    { 
     var menu = new BranchMenu { Name = name }; 
     menu.ParentId = (branchMenu as Menu).Id; 
     branchMenu.AddSubMenu(menu); 
     return new NestSubMenuBuilder(this, menu); 
    } 

    ISubMenuBuilder ISubMenuBuilder.AddLeaf(string name) 
    { 
     this.AddLeaf(name); 
     return this; 
    } 

    IMenuBuilder ISubMenuBuilder.Build() 
    { 
     return subMenuBuilder; 
    } 

    IMenuBuilder IMenuBuilder.AddLeaf(string name) 
    { 
     this.AddLeaf(name); 
     return this; 
    } 

    ISubMenuBuilder IMenuBuilder.AddBranch(string name) 
    { 
     this.AddBranch(name); 
     return this; 
    } 

    void IMenuBuilder.Build() 
    { 
    } 
} 

が、これは私のビルダーのコードであり、ここで、このビルダーのAPIを使用している間、私は問題を得た例です。

 builder 
       .AddLeaf("Leaf 4") 
       .AddBranch("Branch 2") // subMenuBuilder 
        .AddLeaf("Branch 2 -> Leaf 1") 
        .AddBranch("Branch 2 -> Branch 1") //nestSubMenuBuilder 1 
          .AddLeaf("Branch 2 -> Branch 1 -> Leaf 3") 
          .AddBranch("Branch 2 -> Branch 1 -> Branch 1") //nestSubMenuBuilder 2 
           .AddLeaf("Branch 2 -> Branch 1 -> Branch 1 -> Leaf 1") 
           .Build() // nestSubMenuBuilder 1 
          .AddLeaf("Branch 2 -> Leaf 4") 
          .Build() // subMenuBuilder 
        .AddLeaf("Branch 2 -> Leaf 2") 
        .Build();// menubuilder 

ここでは、新しいリーフとブランチを追加するために最後のメニュービルダーのリファレンスを取得していません。

+0

イム方法。 –

+0

'void Build()'メソッドが追加されても問題はありませんか?あなたは何のAPIを使用していますか(それに関連するタグやいくつかのドキュメントAPIがありますか?)これはコードレビューの質問によく似ていますか?最初の 'IMenuBuilder'があなたのインターフェースの' Build'メソッドの所有者ではない理由と、subInterfacesを上書きする理由は分かりません。オーバーライドするsubInterfacesはビルドメソッドを変更すべきではありません。すべての場合に 'IMenuBuilder'を返すだけです。 – Icepickle

+0

「今私は問題を引き起こしていません...」私をとてもひどく壊しました:D –

答えて

1

問題は、コードが各メニューレベルに対して別のビルダーオブジェクトを返すことです。代わりに、あなたは常にビルダーの同じ種類を返す必要があり、トップレベルに達したとき、ちょうどBuild()からnullを返す

提案ビルダーコード:最後のビルド時の初期メニュービルダー参照を取得することはできません

public interface IMenuBuilder 
{ 
    IMenuBuilder AddLeaf(string name); 
    IMenuBuilder AddBranch(string name); 
    IMenuBuilder Build(); 
} 

public class MenuBuilder : IMenuBuilder 
{ 
    private IMenuBuilder menuBuilder; 
    private ISubMenuHolder menu; 

    /// <summary> 
    /// Create a new menu with specified root item 
    /// </summary> 
    public MenuBuilder(string rootName) 
    { 
     this.menuBuilder = null; 
     this.menu = new RootMenu { Name = rootName }; 
    } 

    /// <summary> 
    /// Create a new sub menu with specified parents 
    /// </summary> 
    public MenuBuilder(IMenuBuilder parentBuilder, ISubMenuHolder menu) 
    { 
     this.menuBuilder = parentBuilder; 
     this.menu = menu; 
    } 

    public IMenuBuilder AddLeaf(string name) 
    { 
     var leafMenu = new LeafMenu { Name = name }; 
     leafMenu.ParentId = menu.Id; 
     menu.AddSubMenu(leafMenu); 
     return this; 
    } 

    public IMenuBuilder AddBranch(string name) 
    { 
     var branchMenu = new BranchMenu { Name = name }; 
     branchMenu.ParentId = menu.Id; 
     menu.AddSubMenu(branchMenu); 
     return new MenuBuilder(this, branchMenu); 
    } 

    public IMenuBuilder Build() 
    { 
     return menuBuilder; 
    } 
} 
+0

ありがとう、アプローチ。 –

関連する問題