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.由于每个生成器是根据数据移步一步构建最终结果,所以能精确的控制生成器构建的每个结果。
    生成器模式有点类似于抽象工厂,两者都是返回由许多方法和对象组成的类,他们之间的主要差别是,抽象工厂返回的是一系列相关的类,而生成器是根据提供的数据一步一步的构建一个复杂的对象。






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

  • 相关阅读:
    硬件的效率与一致性
    深入理解SPI机制-服务发现机制
    spring 之7种重要设计模式
    list里放map list 放list
    jvm 三种编译
    几种不同格式的json解析
    Java知识点梳理——集合
    判断2个list中是否有相同的数据(相交)Collections.disjoint
    键相同,比较两个map中的值是否相同
    Map类型数据导出Excel--poi
  • 原文地址:https://www.cnblogs.com/sunjinpeng/p/2420862.html
Copyright © 2011-2022 走看看