C# 生成器模式(一个投资跟踪程序)
一个投资跟踪程序
我们考虑一个稍微简单一点的例子,在这个例子中,用一个类构造一个用户界面。假设我
们要编写一个程序来跟踪投资的效益。我们有股票、债券和基金等投资项目,对每一种投资项
目都要显示持有量的列表,这样就能够选择一种或多种投资项目并在图上标注出它们之间的效
益对比。
尽管不能事先预测在给定的时间内每种投资项目的拥有量,但我们还是希望,无论是对大数量
的投资项目(例如股票),还是小数量的投资项目〔例如基金),都有一种易于使用的显示方式。每
种情况下我们都想要一种多选显示,这样就能够选择一个或多个项目来标注。如果投资项目的数量
大,可以使用一个多选的列表框显示;如果只有三个或更少的项目,则使用几个复选框来表示。让
Builder类根据需要显示的项目个数生成界面,同时还要有相同的方法来返回结果。
下图是包含了少量债
券的显示。接下来我们考虑如何构造界面,来完成这种不同的显示。先创建一个multiChoice接口,
它定义了需要实现的方法。
public interface MultiChoice
{ArrayList getSelected();void clear();Panel getWindow();
}
C#在设计生成器类方面具有相当大的灵活性,我们可以直接访问这样一些方法,这些方法允
许我们由基本组件构建一个窗口。对本例来说,让每个生成器构建一个包含所需组件的面板,然后
将面板添加到窗体中,并确定它的位置。当改变显示时,删除旧的面板,添加上新的面板。在C#
里,面板只是一个无边框的、能包含多个windows组件的容器。这里面板的两种实现过程都必须
满足multiChoice接口。
接下来创建一个抽象基类Equities,并由它派生出Stocks,Bonds和Mutuals类。
public abstruct class Equities
{protected ArrayList array;public abstract string ToString();public ArrayList getNames(){return array;}public int Count(){return array.Count;}
}
注意抽象方法Tostring,我们用该方法在列表框中显示每种股票。Stocks类只包含了向ArrayList
中添加股票名称的代码。
public class Stocks.Equities
{public Stocks(){array=new ArrayList();array.Add("Cisco");array.Add("Coca Cola");array.Add("GE");array.Add("Harley Davidson");array.Add("IBM");array.Add("Microsoft");}public override string ToString(){return "Stocks";}
}
其余的全部代码(getNames方法和count方法)已经在基类Equities实现。Bonds类和Mutuals
类与此完全类似。
StockFactory
我们需要一个简单的来决定,要返回的是一个复选框面板还是一个列表框面板。我们把这个
类称为StockFactory。由于我们只需要该类的一个实例,因而在创建该类时让其中的一个方法为静
态的。
public class StockFactory
{public static MultiChoice getBuilder(Equities stocks){if(stocks.count()<=3){return new CheckChoice(stocks);}else{return new ListChoice(stocks);}}
}
由于只需要该类的一个实例,所以我们把getBuilder方法声明为静态的,然后就可以直接调用
它而无需创建该类的实例。用设计模式的语言来讲,这个简单工厂类叫做Director,而由multiChoice
类派生出来的实际类就是Builder。
CheckChoice类
这里的复选框生磽器构建了一个包含0到3个复选框的面板,并将面板返回给调用程序。
public class checkChoice:MultiChoice
{private ArrayList stocks;private Panel panel;private ArrayList boxes;public checkChoice(Equities stks){stocks=stks.getNames();panel=new Panel();boxes=new ArrayList();for(int i=0;i<stocks.Count;i++){CheckBox ck=new CheckBox();ck.Location=new Point(8,16+i*32);string stk=(string)stocks[i];ck.Text=stk;ck.Size=new Size(112,24);ck.TabIndex=0;ck.TextAlign=ContentAlignment.MiddleLeft;boxes.Add(ck);panel.Controls.Add(ck);}}
}
返回窗口和选中名称列表的方法吓所示。注意,这里把由ArrayList返回的对象类型转换为
该方法实际需要的CheckBox类型。
public void clear()
{for(int i=0;i<boxes.Count;i++){CheckBox ck=(CheckBox)boxes[i];ck.Checked=false;}
}public ArrayList getSelected()
{ArrayList sels=new ArrayList();for(int i=0;i<boxes.Count;i++){CheckBox ck=(CheckBox)boxes[i];for(int i=0;i<boxes.Count;i++){CheckBox ck=(CheckBox)boxes[i];if(ck.Checked){sels.Add(ck.Text);}}return sels;}public Panel getWindow(){return panel;}
}
ListboxChoice类
该类创建一个多选列表框,并将其插人到一个面板中,然后将名称加到列表里。
public class ListChoice:MultiChoice
{private ArrayList stocks;private Panel panel;private ListBox list;public ListChoice(Equities stks){stocks=stks.getNames();panel=new Panel();list=new ListBox();list.Location=new Point(16,0);list.Size=new Size(120,160);list.SelectionMode=SelectionMode.MultiExtented;list.TabIndex=0;panel.Controls.Add(list);for(int i=0;i<stocks.Count;i++)list.Items.Add(stocks[i]);}
}
由于这是一个多选列表框,我们可以把所有选中的项目都存放在一个selectedlndlces集合中。
该方法只对多选列表框起作用,对于单选列表框它只返回一个1。这里用这种方法将选中的名称加
到ArrayList中,程序如下所示。
public Panel getWindow()
{return panel_;
}public ArrayList getSelected()
{ArrayList sels=new ArrayList();ListBox.SelectedObjectCollection coll=list.SelectedItems;for(int i=0;i<coll.Count;i++){string item=(string)coll[i];sels.Add(item);}return sels;
}public void clear()
{list.Items.Clear();
}