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

    生成器模式(Builder Pattern)
        将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。生成器模式是一步一步创建一个复杂的对象,它允许用户可以只通过指定复杂对象的类型和内容就可以构建它们。用户不知道内部的具体构建细节。Builder模式是非常类似抽象工厂模式,细微的区别大概只有在反复使用中才能体会到。

        假设需要构建一个用户界面,改页面可以根据数据量大小显示不同的风格。以投资跟踪效益程序为例

    图1、 图2、

    尽管不能事先预测在给定的时间内每种项目拥有量,但我们还是希望无论打数据量还是小数据量都能够有种直观的显示方式。我们设定两种显示方式,列表模式和多选模式。先看三种投资方式代码:

    Equities 接口
            public abstract class Equities
    {
    protected ArrayList array;
    public abstract string ToString();
    public ArrayList GetNames()
    {
    return array;
    }

    public int Count()
    {
    return array.Count;
    }
    }
    三个模板类
            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("NEC");
    }

    public override string ToString()
    {
    return "Stocks";
    }
    }

    public class Bonds : Equities
    {
    public Bonds()
    {
    base.array = new ArrayList();
    array.Add("CI");
    array.Add("MS");
    array.Add("QQ");
    }
    public override string ToString()
    {
    return "Bonds";
    }
    }

    public class Mutuals : Equities
    {
    public Mutuals()
    {
    base.array = new ArrayList();
    array.Add("CI");
    array.Add("MS");
    array.Add("QQ");
    array.Add("CNKI");
    array.Add("LENOVO");
    }
    public override string ToString()
    {
    return "Mutuals";
    }
    }

    上面代码定义了Stocks,Bonds和Mutuals三个类用于得到每种投资种类的具体投资方式。下面定义两种显示方式

    MultiChoice 接口
            public interface MultiChoice
    {
    void Clear();
    Panel GetWindow();
    ArrayList GetSelected();
    }
    两种显示方式
            public class CheckChoice : MultiChoice
    {
    private ArrayList arr;
    private ArrayList boxes;
    private Panel panel;
    public CheckChoice(Equities equ)
    {
    arr = equ.GetNames();
    panel = new Panel();
    boxes = new ArrayList();

    for (int i = 0; i < arr.Count; i++)
    {
    CheckBox cb = new CheckBox();
    cb.Location = new Point(8, 16 + i * 32);
    cb.Text = arr[i].ToString();
    boxes.Add(cb);
    panel.Controls.Add(cb);
    }
    }

    #region MultiChoice 成员

    public void Clear()
    {
    foreach (var item in boxes)
    {
    CheckBox cb = item as CheckBox;
    cb.Checked = false;
    }
    }

    public Panel GetWindow()
    {
    return panel;
    }

    public ArrayList GetSelected()
    {
    ArrayList names = new ArrayList();
    foreach (var item in boxes)
    {
    CheckBox cb = item as CheckBox;
    if (cb.Checked)
    {
    names.Add(cb.Text);
    }
    }

    return names;
    }

    #endregion
    }

    public class ListChoice : MultiChoice
    {
    private ArrayList arr;
    private ListBox lBox;
    private Panel panel;
    public ListChoice(Equities equ)
    {
    arr = equ.GetNames();
    panel = new Panel();
    lBox = new ListBox();
    // lBox.Location = new Point(180, 10);

    panel.Controls.Add(lBox);
    for (int i = 0; i < arr.Count; i++)
    {
    lBox.Items.Add(arr[i]);
    }
    }

    #region MultiChoice 成员

    public void Clear()
    {
    lBox.Items.Clear();
    }

    public Panel GetWindow()
    {
    return panel;
    }

    public ArrayList GetSelected()
    {
    ArrayList names = new ArrayList();
    foreach (var item in lBox.SelectedItems)
    {
    names.Add(item);
    }

    return names;
    }

    #endregion
    }

    他们直接的关系怎么链接那? 用到前面介绍的简单工厂模式。

    Factory
            public class Factory
    {
    public static MultiChoice GetChoice(Equities equ)
    {
    if (equ.Count() > 3) // 更像简单工厂模式
    {
    return new ListChoice(equ);
    }
    else
    return new CheckChoice(equ);
    }
    }

    具体调用起来就简单了,直接调用工厂类的静态方法。添加到窗体的代码:

    View Code
            private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
    {
    Equities eq = null;
    string s = listBox1.SelectedItem.ToString();
    if (s == "Stocks")
    {
    eq = new Stocks();
    }
    else if (s == "Bonds")
    {
    eq = new Bonds();
    }
    else if (s == "Mutuals")
    {
    eq = new Mutuals();
    }

    panel1.Controls.Clear();
    MultiChoice ch = Factory.GetChoice(eq);
    panel1.Controls.Add(ch.GetWindow());
    }

    这样,整个生成器模式就完成了??? 有的晕吧? 像简单工程,也像抽象工程。下面说说两者直接的区别:

        从形式上来讲,通过角色合并,方法功能的转变,抽象工厂可以和生成器模式形式上取得一致(比如抽象工厂只处理一个产品族,工厂方法都处理同一个产品)。但注意,这仅仅是形式上的,实际上,抽象工厂和生成器模式有着本质的区别

    1、生成器模式是为了构造一个复杂的产品,而且购造这个产品遵循一定的规则(相同的过程),而抽象工厂则是为了创建成族的产品(系列产品),同族产品的构造在逻辑上并不存在必然的联系(唯一必然的联系就是大家都属于一族)。

    2、生成器模式的构造方法是为了构造同一个产品,因此必须有指导者来协调进行工作,构造方法之间存在必然的业务联系,而抽象工厂的构造方法都是独立去构建自己的产品对象,因此他们不存在必然的联系。在生成器模式中客户端不直接调用构建产品部分的方法来获取最终产品,而抽象工厂中客户端是通过调用不同的工厂方法获取不同的产品。

    3.在生成器模式中,那些用来构造产品不同部分的方法一般都实现为Protected形式,以防止客户端通过调用这种方法活得不可预料的结果,而抽象工厂中的这些方法必须为Public形式。否则客户无法调用来获得产品结果;

    4.生成器模式的角色有生成器,产品和指导者,而抽象工厂的角色有工厂和产品。无论角色和功能怎样变换,但所含的业务逻辑角色都应该存在,这也是两个模式的业务本质。

    本人初学,对上面两种模式也没有理解透。工作中慢慢理解了






    ———————————————————————————————————————— 

     一个人的时候,总是在想

        我的生活到底在期待什么……

  • 相关阅读:
    sql server模糊查询、分组
    glup watch reload 保存 刷新 原理
    a daemon 守护进程 shell命令行以&结尾
    单道程序 多道程序
    10.6 Comment Syntax
    Bash is an sh-compatible command language interpreter that executes commands read from the standard input or from a file.
    在常见的机器学习/深度学习项目里,数据准备占去整个分析管道的60%到80%。
    算法所产生的性能改进已经超过了硬件所带来的性能提升 The future is algorithms, not code
    postgresql_action
    InnoDB Crash Recovery InnoDB崩溃恢复
  • 原文地址:https://www.cnblogs.com/freeton/p/2274830.html
Copyright © 2011-2022 走看看