zoukankan      html  css  js  c++  java
  • 设计模式 生成器模式(builder Pattern)

      生成器模式又称建造者模式,定义一个抽象的建造者的角色(Builder),规定所有具体的建造者都应该具有的功能——这些功能就是如何创建复杂对象的某个特定部分(子对象),而具体如何创建子对象有具体的创建者实现。再定义一个指导者的角色,它把创建者作为工具,知道如何使用这个工具来创建复杂对象。这样,客户在需要创建这个复杂对象的时候,只需要给指导者一个具体的创建者就可以了。至于具体创建者如何创建子对象的细节以及这些子对象之间的差异,不是指导者,也不是客户关心的。
      下面我们用一个例子来说明一下生成器模式,假设我们不但需要一个计算的算法,还需要一个由于显示数据根据数据不同而完全不同的用户界面。我们考虑一个简单的例子,在这个例子中,用一个类构造一个用户界面。假设我们要编写一个程序跟踪投资效益。我们有股票、基金、债券等N个投资项目,对每个投资项目都要显示持有量列表,无论对于大数量的投资(股票)还是小数目的投资(基金),都有一种易于使用的显示方式。每种情况我们都想多选显示。如果投资项目的数量大,可以使用多选列表框,如果等于或小于三个项目,则使用复选框代替。让Builder类根据需要显示项目生成的界面,同时还要有相同的方法来返回。
      我们的程序运行结构图如下,左边是少量数据,右边是大量数据。

      接下来我们考虑如何构建界面,来完成不同的显示。首先创建MultiChoice接口,里边定义了需要实现的方法。

     1 using System;
    2 using System.Collections ;
    3 using System.Windows.Forms;
    4
    5
    6 /// <summary>
    7 /// Summary description for MultiChoice.
    8 /// </summary>
    9 public interface MultiChoice
    10 {
    11 ArrayList getSelected();
    12 void clear();
    13 Panel getWindow();
    14 }

      getWindow方法返回一个包含多选显示的面板(panel),这里使用两个显示面板实现该界面一个是复选框面板,一个是列表面板。

    1     public class CheckChoice:MultiChoice     {

      或

    1     public class ListChoice:MultiChoice {

      接下来创建一个抽象类Equities,并有它派生出Stocks(股票),Bonds(债券),Mutuals(基金)类。

     1 using System;
    2 using System.Collections ;
    3
    4
    5 /// <summary>
    6 /// Summary description for Equities.
    7 /// </summary>
    8 public abstract class Equities {
    9 protected ArrayList array;
    10 public abstract string ToString();
    11 //----------
    12 public ArrayList getNames() {
    13 return array;
    14 }
    15 //----------
    16 public int count() {
    17 return array.Count ;
    18 }
    19 }

      Stocks

     1 using System;
    2 using System.Collections ;
    3
    4
    5
    6 /// <summary>
    7 /// Summary description for Stocks.
    8 /// </summary>
    9 public class Stocks:Equities {
    10 public Stocks() {
    11 array = new ArrayList();
    12 array.Add ("Cisco");
    13 array.Add ("Coca Cola");
    14 array.Add ("GE");
    15 array.Add ("Harley Davidson");
    16 array.Add ("IBM");
    17 array.Add ("Microsoft");
    18 }
    19 public override string ToString() {
    20 return "Stocks";
    21 }
    22 }

    Bonds(债券),Mutuals(基金)类代码基本类似....

      我们还需要一个简单的类来决定,要返回的是一个复选框面板还是一个列表框面板。我们把这个类称为StockFactory。由于我们只需要该类的一个实例,因而创建该类时让其中的一个方法为静态的。我们也可以把这个类称为简单工厂。

     1 using System;
    2
    3
    4 /// <summary>
    5 /// Summary description for StockFactory.
    6 /// </summary>
    7 public class StockFactory
    8 {
    9 public static MultiChoice getBuilder(Equities stocks)
    10 {
    11 if (stocks.count ()<=3) {
    12 return new CheckChoice (stocks);
    13 }
    14 else {
    15 return new ListChoice(stocks);
    16 }
    17 }
    18 }

      CheckChoice类,这里生成0-3个复选框的面板,并且将面板返回。

     1 using System;
    2 using System.Collections ;
    3 using System.Windows.Forms ;
    4 using System.Drawing ;
    5
    6
    7 //returns a panel of 0 to 3 check boxes
    8 public class CheckChoice:MultiChoice {
    9 private ArrayList stocks;
    10 private Panel panel;
    11 private ArrayList boxes;
    12 //------
    13 public CheckChoice(Equities stks) {
    14 stocks = stks.getNames ();
    15 panel = new Panel ();
    16 boxes = new ArrayList ();
    17 //add the check boxes to the panel
    18 for (int i=0; i< stocks.Count; i++) {
    19 CheckBox ck = new CheckBox ();
    20 //position them
    21 ck.Location = new Point (8, 16 + i * 32);
    22 string stk = (string)stocks[i];
    23 ck.Text =stk;
    24 ck.Size = new Size (112, 24);
    25 ck.TabIndex =0;
    26 ck.TextAlign = ContentAlignment.MiddleLeft ;
    27 boxes.Add (ck);
    28 panel.Controls.Add (ck);
    29 }
    30 }
    31 //------
    32 //uncheck all check boxes
    33 public void clear() {
    34 for(int i=0; i< boxes.Count; i++) {
    35 CheckBox ck = (CheckBox)boxes[i];
    36 ck.Checked =false;
    37 }
    38 }
    39 //------
    40 //return list of checked items
    41 public ArrayList getSelected() {
    42 ArrayList sels = new ArrayList ();
    43 for(int i=0; i< boxes.Count ; i++) {
    44 CheckBox ck = (CheckBox)boxes[i];
    45 if (ck.Checked ) {
    46 sels.Add (ck.Text );
    47 }
    48 }
    49 return sels;
    50 }
    51 //------
    52 //return panel of checkboxes
    53 public Panel getWindow() {
    54 return panel;
    55 }
    56 }

      ListBoxChoice类,该类创建一个多选框列表,并且将其插入到一个面板中,然后显示名称。

     1 using System;
    2 using System.Collections ;
    3 using System.Windows.Forms ;
    4 using System.Drawing ;
    5
    6 /// <summary>
    7 /// Summary description for ListChoice.
    8 /// </summary>
    9 /// creates a Panel containing a list box
    10 public class ListChoice:MultiChoice {
    11 private ArrayList stocks;
    12 private Panel panel;
    13 private ListBox list;
    14 //------
    15 //constructor creates and loads the list box
    16 public ListChoice(Equities stks) {
    17 stocks = stks.getNames ();
    18 panel = new Panel ();
    19 list = new ListBox ();
    20 list.Location = new Point (16, 0);
    21 list.Size = new Size (120, 160);
    22 list.SelectionMode =SelectionMode.MultiExtended ;
    23 list.TabIndex =0;
    24 panel.Controls.Add (list);
    25 for(int i=0; i< stocks.Count ; i++) {
    26 list.Items.Add (stocks[i]);
    27 }
    28 }
    29 //returns the Panel
    30 //------
    31 public Panel getWindow() {
    32 return panel;
    33 }
    34 //returns an array of selected elements
    35 //------
    36 public ArrayList getSelected() {
    37 ArrayList sels = new ArrayList ();
    38 ListBox.SelectedObjectCollection coll = list.SelectedItems ;
    39 for(int i=0; i< coll.Count; i++) {
    40 string item = (string)coll[i];
    41 sels.Add (item );
    42 }
    43 return sels;
    44 }
    45 //------
    46 //clear selected elements
    47 public void clear() {
    48 list.Items.Clear();
    49 }
    50 }

      在使用列表框的时,列表框中值不仅限于字符串,在添加的数据中,可以使具有ToString方法的任何类型的对象。

     1     private ListBox lsEquities;
    2 /// <summary>
    3 /// Required designer variable.
    4 /// </summary>
    5 private Container components = null;
    6 private Button btPlot;
    7 private Panel pnl;
    8 private MultiChoice mchoice;
    9 private void init() {
    10 lsEquities.Items.Add (new Stocks());
    11 lsEquities.Items.Add (new Bonds());
    12 lsEquities.Items.Add (new Mutuals());
    13 }
    14 public WealthBuilder()
    15 {
    16 InitializeComponent();
    17 init();
    18 }

      在单击列表框中第一行数据时,单击方法会获得相应的Equities类的实例,将该实例传给MultiChoice工厂,接下来在相应的类中生成一个包含项目的面板,然后删除旧的面板,添加新的面板。

     1 private void lsEquities_SelectedIndexChanged(object sender, System.EventArgs e) {
    2 int i = lsEquities.SelectedIndex ;
    3 Equities eq = (Equities)lsEquities.Items[i];
    4 mchoice= StockFactory.getBuilder (eq);
    5 this.Controls.Remove (pnl);
    6 pnl = mchoice.getWindow ();
    7 setPanel();
    8 }
    9
    10 private void setPanel() {
    11 pnl.Location = new Point(152, 24);
    12 pnl.Size = new Size(128, 168);
    13 pnl.TabIndex = 1;
    14 Controls.Add(pnl);
    15 }

    在本里中,我们并没有实现真正的标注,只是弹出选中的值。

     1         private void btPlot_Click(object sender, System.EventArgs e) {
    2 //display the selected items in a message box
    3 if(mchoice != null) {
    4 ArrayList ar = mchoice.getSelected ();
    5 string ans = "";
    6 for(int i=0; i< ar.Count ; i++) {
    7 ans += (string)ar[i] +" ";
    8 }
    9 MessageBox.Show (null, ans, "Selected equities", MessageBoxButtons.OK );
    10 }
    11 }


    生成器模式效果
    1.生成器允许读者改变产品的内部表示,同时也隐藏了产品的组装细节。
    2.每个特定的生成器都独立于其他的生成器,同时也独立于程序的其他部分,这一点提高了对象模块性,并使用添加其他的生成器变得简单。
    3.由于每个生成器是根据数据移步一步构建最终结果,所以能精确的控制生成器构建的每个结果。
    生成器模式有点类似于抽象工厂,两者都是返回由许多方法和对象组成的类,他们之间的主要差别是,抽象工厂返回的是一系列相关的类,而生成器是根据提供的数据一步一步的构建一个复杂的对象。






    人生如棋、我愿为卒、行动虽缓、从未退过

  • 相关阅读:
    PAT (Advanced Level) 1086. Tree Traversals Again (25)
    PAT (Advanced Level) 1085. Perfect Sequence (25)
    PAT (Advanced Level) 1084. Broken Keyboard (20)
    PAT (Advanced Level) 1083. List Grades (25)
    PAT (Advanced Level) 1082. Read Number in Chinese (25)
    HDU 4513 吉哥系列故事――完美队形II
    POJ Oulipo KMP 模板题
    POJ 3376 Finding Palindromes
    扩展KMP
    HDU 2289 Cup
  • 原文地址:https://www.cnblogs.com/sunjinpeng/p/2420862.html
Copyright © 2011-2022 走看看