C# 生成器模式(一个投资跟踪程序)

一个投资跟踪程序

我们考虑一个稍微简单一点的例子,在这个例子中,用一个类构造一个用户界面。假设我

们要编写一个程序来跟踪投资的效益。我们有股票、债券和基金等投资项目,对每一种投资项

目都要显示持有量的列表,这样就能够选择一种或多种投资项目并在图上标注出它们之间的效

益对比。

尽管不能事先预测在给定的时间内每种投资项目的拥有量,但我们还是希望,无论是对大数量

的投资项目(例如股票),还是小数量的投资项目〔例如基金),都有一种易于使用的显示方式。每

种情况下我们都想要一种多选显示,这样就能够选择一个或多个项目来标注。如果投资项目的数量

大,可以使用一个多选的列表框显示;如果只有三个或更少的项目,则使用几个复选框来表示。让

Builder类根据需要显示的项目个数生成界面,同时还要有相同的方法来返回结果。

下图是包含了少量债

券的显示。接下来我们考虑如何构造界面,来完成这种不同的显示。先创建一个multiChoice接口,

它定义了需要实现的方法。

csharp 复制代码
public interface MultiChoice
{
    ArrayList getSelected();
    void clear();
    Panel getWindow();
}

C#在设计生成器类方面具有相当大的灵活性,我们可以直接访问这样一些方法,这些方法允

许我们由基本组件构建一个窗口。对本例来说,让每个生成器构建一个包含所需组件的面板,然后

将面板添加到窗体中,并确定它的位置。当改变显示时,删除旧的面板,添加上新的面板。在C#

里,面板只是一个无边框的、能包含多个windows组件的容器。这里面板的两种实现过程都必须

满足multiChoice接口。

接下来创建一个抽象基类Equities,并由它派生出Stocks,Bonds和Mutuals类。

csharp 复制代码
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

中添加股票名称的代码。

csharp 复制代码
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。由于我们只需要该类的一个实例,因而在创建该类时让其中的一个方法为静

态的。

csharp 复制代码
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个复选框的面板,并将面板返回给调用程序。

csharp 复制代码
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类型。

csharp 复制代码
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类

该类创建一个多选列表框,并将其插人到一个面板中,然后将名称加到列表里。

csharp 复制代码
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中,程序如下所示。

csharp 复制代码
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();
}