您的位置:首页 > 产品设计 > UI/UE

《模式――工程化实现及扩展》(设计模式C# 版)《连贯接口 Fluent Interface》――“自我检验"参考答案

2011-06-01 22:12 866 查看
转自:《模式——工程化实现及扩展》(设计模式C# 版)

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

/article/5123621.html的参考答案

参考答案

设计要点:

采用连贯接口设计表格的创建过程

由于表格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接口的有效性
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐