《模式——工程化實現及擴充》(設計模式C# 版)《連貫介面 Fluent Interface》——“自我檢驗”參考答案

來源:互聯網
上載者:User

轉自:《模式——工程化實現及擴充》(設計模式C# 版)

http://www.cnblogs.com/callwangxiang/

 

 

http://www.cnblogs.com/callwangxiang/archive/2011/05/31/ExerciseAAFluentInterface.html的參考答案

 

 

參考答案

 

設計要點:

  1. 採用連貫介面設計表格的建立過程
  2. 由於表格Head涉及一層嵌套、Body涉及兩層嵌套,因此為了便於調整和修改,每個節點元素類型都要保留回溯到父節點的引用

 

1、設計具有Fluent特徵的抽象節點類型

/// <summary>/// 修改後具有Fluent特徵的集合類型/// </summary>/// <typeparam name="T">集合元素類型</typeparam>/// <typeparam name="TParent">父節點類型</typeparam>class FluentCollection<TElement, TParent>    where TElement : class     where TParent : class {    protected List<TElement> list = new List<TElement>();    TParent parent;    public FluentCollection(TParent parent)    {        if(parent == null) throw new ArgumentNullException("parent");        this.parent = parent;    }    /// <summary>    /// 返回父節點    /// </summary>    public TParent Parent{get{ return parent;}}    /// <summary>    /// 如何獲得一個TElement類型執行個體的委託    /// </summary>    public Func<TElement> GetInstance { get; set; }    /// <summary>    /// 具有fluent特徵的追加操作    /// </summary>    /// <param name="t"></param>    /// <returns></returns>    public FluentCollection<TElement, TParent> Add(TElement t)    {        list.Add(t);        return this;    }    /// <summary>    /// 具有fluent特徵的空置操作    /// </summary>    /// <returns></returns>    public FluentCollection<TElement, TParent> Skip    {        get        {            list.Add(GetInstance());            return this;        }    }    /// <summary>    /// 執行LINQ的foreach操作    /// </summary>    /// <param name="action"></param>    public void ForEach(Action<TElement> action)    {        list.ForEach(action);    }}/// <summary>/// 父節點為table的元素/// </summary>class WithTableObject{    Table table;    //  父節點    public WithTableObject(Table table)    {        if(table == null) throw new ArgumentNullException("table");        this.table = table;    }    /// <summary>    /// 指向父節點——table    /// </summary>    public Table Parent{get{ return table;}}}

 

2、定義各個節點類型

class Notation{    public Notation(){Data = string.Empty;}    public Notation(string data) {Data = data; }    public string Data { get; private set; }}/// <summary>/// n元素/// </summary>class Item : Notation{    public Item():base(){}    public Item(string data) : base(data){}}/// <summary>/// col 元素/// </summary>class Column : Notation{    public Column():base(){}    public Column(string data) : base(data) { }}/// <summary>/// line 元素 /// </summary>class Line{    FluentCollection<Item, Line> items;    Body body;    public Line(Body body)    {        if(body == null) throw new ArgumentNullException("body");        this.body = body;        items = new FluentCollection<Item, Line>(this)                    {                        GetInstance = () => { return new Item(); }                    };    }    /// <summary>    /// 父節點    /// </summary>    public Body Body { get { return body; } }            public FluentCollection<Item, Line> Items { get { return items; } }    public Line NewLine{get{return body.NewLine;}}}/// <summary>/// body 元素/// </summary>class Body : WithTableObject{    List<Line> lines = new List<Line>();    public Body(Table table) : base(table){}    public Line NewLine    {        get        {            var line = new Line(this);            lines.Add(line);            return line;        }    }    public List<Line> Lines { get { return lines;}}} /// <summary>/// head 元素/// </summary>class Head : WithTableObject{    FluentCollection<Column, Head> columns;    public Head(Table table) : base(table)    {        columns = new FluentCollection<Column, Head>(this)                        {                            GetInstance = () => { return new Column(); }                        };    }            public FluentCollection<Column, Head> Columns { get { return columns; } }}    class Table{    string name;    Body body;    Head head;    public Table()    {        body = new Body(this);        head = new Head(this);    }    public Table Name(string name)    {        if(string.IsNullOrEmpty(name)) throw new ArgumentNullException("name");        this.name = name;        return this;    }    public override string ToString(){return name;}    public Body Body{get{ return body;}}    public Head Head{get{ return head;}}}

 

3、定義產生試算表的資料類型

class Notation{    public Notation(){Data = string.Empty;}    public Notation(string data) {Data = data; }    public string Data { get; private set; }}/// <summary>/// n元素/// </summary>class Item : Notation{    public Item():base(){}    public Item(string data) : base(data){}}/// <summary>/// col 元素/// </summary>class Column : Notation{    public Column():base(){}    public Column(string data) : base(data) { }}/// <summary>/// line 元素 /// </summary>class Line{    FluentCollection<Item, Line> items;    Body body;    public Line(Body body)    {        if(body == null) throw new ArgumentNullException("body");        this.body = body;        items = new FluentCollection<Item, Line>(this)                    {                        GetInstance = () => { return new Item(); }                    };    }    /// <summary>    /// 父節點    /// </summary>    public Body Body { get { return body; } }            public FluentCollection<Item, Line> Items { get { return items; } }    public Line NewLine{get{return body.NewLine;}}}/// <summary>/// body 元素/// </summary>class Body : WithTableObject{    List<Line> lines = new List<Line>();    public Body(Table table) : base(table){}    public Line NewLine    {        get        {            var line = new Line(this);            lines.Add(line);            return line;        }    }    public List<Line> Lines { get { return lines;}}} /// <summary>/// head 元素/// </summary>class Head : WithTableObject{    FluentCollection<Column, Head> columns;    public Head(Table table) : base(table)    {        columns = new FluentCollection<Column, Head>(this)                        {                            GetInstance = () => { return new Column(); }                        };    }            public FluentCollection<Column, Head> Columns { get { return columns; } }}    class Table{    string name;    Body body;    Head head;    public Table()    {        body = new Body(this);        head = new Head(this);    }    public Table Name(string name)    {        if(string.IsNullOrEmpty(name)) throw new ArgumentNullException("name");        this.name = name;        return this;    }    public override string ToString(){return name;}    public Body Body{get{ return body;}}    public Head Head{get{ return head;}}}

 

 

4、單元測試

[TestClass]public class FluentInterfaceFixture{    TableWriter writer;    [TestInitialize]      public void Initialize()    {        writer = new TableWriter();    }    [TestMethod]    public void TestFullFillTable()    {        writer.Output(            new Table()                .Name("full fill")                .Head                    .Columns                        .Add(new Column("first"))                        .Add(new Column("second"))                        .Add(new Column("thrid"))                    .Parent                .Parent                .Body                    .NewLine.Items.Add(new Item("11")).Add(new Item("12")).Add(new Item("13")).Parent                    .NewLine.Items.Add(new Item("21")).Add(new Item("22")).Add(new Item("23")).Parent                .Body            .Parent            );    }    [TestMethod]    public void TestSkipColumnTable()    {        writer.Output(            new Table()                .Name("skip columns")                .Head                    .Columns                        .Add(new Column("first"))                        .Skip                        .Add(new Column("thrid"))                    .Parent                .Parent                .Body                    .NewLine.Items.Add(new Item("11")).Add(new Item("12")).Add(new Item("13")).Parent                    .NewLine.Items.Add(new Item("21")).Add(new Item("22")).Add(new Item("23")).Parent                .Body            .Parent            );    }    [TestMethod]    public void TestSkiItemsTable()    {        writer.Output(            new Table()                .Name("skip items")                .Head                    .Columns                        .Add(new Column("first"))                        .Add(new Column("second"))                        .Add(new Column("thrid"))                    .Parent                .Parent                .Body                    .NewLine.Items.Add(new Item("11")).Skip.Add(new Item("13")).Parent                    .NewLine.Items.Add(new Item("21")).Add(new Item("22")).Skip.Parent                .Body            .Parent            );    }    [TestMethod]    public void TestSkipColumnsAndItemsTable()    {        writer.Output(            new Table()                .Name("skip columns and items")                .Head                    .Columns                        .Add(new Column("first"))                        .Skip                        .Add(new Column("thrid"))                    .Parent                .Parent                .Body                    .NewLine.Items.Add(new Item("11")).Skip.Add(new Item("13")).Parent                    .NewLine.Items.Add(new Item("21")).Add(new Item("22")).Skip.Parent                .Body            .Parent            );    }}

 

5、測試結果

------ Test started: Assembly: Concept.Tests.dll ------<table>    <name>full fill</name>    <head><col>first</col><col>second</col><col>thrid</col>        </head>    <body>        <line>        <item><n>11</n><n>12</n><n>13</n>                    </item>        <item><n>21</n><n>22</n><n>23</n>                    </item>    </line>    </body></table><table>    <name>skip columns</name>    <head><col>first</col><col></col><col>thrid</col>        </head>    <body>        <line>        <item><n>11</n><n>12</n><n>13</n>                    </item>        <item><n>21</n><n>22</n><n>23</n>                    </item>    </line>    </body></table><table>    <name>skip items</name>    <head><col>first</col><col>second</col><col>thrid</col>        </head>    <body>        <line>        <item><n>11</n><n></n><n>13</n>                    </item>        <item><n>21</n><n>22</n><n></n>                    </item>    </line>    </body></table><table>    <name>skip columns and items</name>    <head><col>first</col><col></col><col>thrid</col>        </head>    <body>        <line>        <item><n>11</n><n></n><n>13</n>                    </item>        <item><n>21</n><n>22</n><n></n>                    </item>    </line>    </body></table>4 passed, 0 failed, 0 skipped, took 1.29 seconds (MSTest 10.0).

 

測試確認Fluent介面的有效性

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.