本篇文章来自于设计模式一书中的“生成器模式”
本篇中我们学习如何使用生成器模式从部件构建对象,假设我们不但需要一个用于计算的算法,还需要一个根据数据的不同而完全不同的用户界面,典型的例子就是E-mail地址薄,在地址薄中,即有个人信息也有组的信息,而用户希望能根据信息的不同,改变地址薄的显示, 这样在用户屏幕中能显示姓名、公司、E-mail地址和电话号码。另一方面,如果显示一个组的地址页,希望能看到组名、组的职能、成员表及他们的E-mail地址。单击一个人的时候得到一种显示方式,单击一个组的时候得到另一种显示方式。假设所有的E-mail地址都保存在Address类的一个对象里,个人和组都派生于这个基类,如下图。
我们考虑一个简单一点的例子,编写一个程序来跟踪投资的效益。我们有股票、债券和基金等投资项目,对每一种投资项目都要显示特有量的列表。无论是对大数量的投资项目(如股票)还是小数量的投资项目(如基金)都有一种易于使用的显示方式。每种情况下我们都要一种多选显示,这样就能够选择一个或多个项目来标注。如果投资项目的数量大,可以使用一个多选的列表框显示;如果只有三个或更少的项目,则使用几个复选框来表示。让Builder类根据需要显示的项目个数生成界面,同时还要有相同的方法来返回结果。完整的类图如下。
namespace BuilderPattern { public interface IMultiChoice { ArrayList GetSelected(); void Clear(); Panel GetPanel(); } }
GetPanel方法返回一个包含多选显示的面板,这里使用两个显示面板实现该界面,一个是复选框,一个是列表框。
public class ListChoice : IMultiChoice { private ArrayList Stocks; private Panel Panel; private ListBox List; public ListChoice(Equities stocks) { Stocks = stocks.GetNames(); Panel = new Panel(); List = new ListBox { Location = new Point(16, 0), Size = new Size(120, 160), SelectionMode = SelectionMode.MultiExtended }; Panel.Controls.Add(List); foreach (var stks in Stocks) List.Items.Add(stks); } public ArrayList GetSelected() { var sel = new ArrayList(); foreach (string str in List.SelectedItems) sel.Add(str); return sel; } public void Clear() { List.Items.Clear(); } public Panel GetPanel() { return Panel; } }