温故而知新:设计模式之Builder

Builder模式主要用于以下场景:

需要创建一个较复杂的大对象实例,并且构成该对象的子对象可能经常会发生变化,但是组成大对象的算法却相对稳定。

比如:我们做b/s开发时,经常会遇到一些系统要求支持模板/皮肤切换,一个完整的页面由若干子模块组成,不管模板如何变换,子模块的内容/位置如何变化,但组成页面的算法即相对固定。

我们假定每个页面由header,body,footer三个基本模块组成,先抽象出来:

接口抽象部分

#region 把不依赖具体细节的部分(即相当稳定,不变的部分)抽象出来
    public interface IShow
    {
        void Show();
    }

    /// <summary>
    /// 页面头部 抽象类
    /// </summary>
    public abstract class Header : IShow
    {
        public abstract void Show();
    }

    /// <summary>
    /// 页面主体 抽象类
    /// </summary>
    public abstract class Body : IShow
    {
        public abstract void Show();
    }

    /// <summary>
    /// 页面底部 抽象类
    /// </summary>
    public abstract class Footer : IShow
    {
        public abstract void Show();
    }

    /// <summary>
    /// 页面基类 抽象类
    /// </summary>
    public class MainPage
    {
        private List<IShow> _lstParts;

        public List<IShow> Parts
        {
            set { _lstParts = value; }
            get
            {
                if (_lstParts == null)
                {
                    _lstParts = new List<IShow>();
                }
                return _lstParts;
            }
        }

        public void Show()
        {
            for (int i = 0; i < _lstParts.Count; i++)
            {
                _lstParts[i].Show();
            }
            Console.Write("页面构建完毕!");
        }

    }

    /// <summary>
    /// 创建器 抽象类
    /// </summary>
    public abstract class Builder
    {
        //不管页面风格如何变换,下面的这些部件的创建算法,相对要求比较稳定

        public abstract void BuildHeader();

        public abstract void BuildBody();

        public abstract void BuildFooter();

        public abstract MainPage GetPage();

    }
    #endregion

客户端程序依赖于上面的抽象:

代码

/// <summary>
    /// 客户程序
    /// </summary>
    public class PageManager
    {
        Builder _builder;

        public PageManager(Builder b)
        {
            this._builder = b;
        }

        public void Show()
        {
            this._builder.BuildHeader();
            this._builder.BuildBody();
            this._builder.BuildFooter();
            this._builder.GetPage().Show();
        }
    }

最后完成具体模板的实现 :

代码

#region spring风格的具体页面及创建器
    public class SpringHeader : Header
    {
        public override void Show()
        {
            Console.WriteLine("Spring风格的header");
        }
    }

    public class SpringBody : Body
    {
        public override void Show()
        {
            Console.WriteLine("Spring风格的body");
        }
    }

    public class SpringFooter : Footer
    {
        public override void Show()
        {
            Console.WriteLine("Spring风格的footer");
        }
    }

    public class SpringBuilder : Builder
    {
        MainPage _mainPage;

        public SpringBuilder()
        {
            _mainPage = new MainPage();
        }

        public override void BuildHeader()
        {
            _mainPage.Parts.Add(new SpringHeader());
        }

        public override void BuildBody()
        {
            _mainPage.Parts.Add(new SpringBody());
        }

        public override void BuildFooter()
        {
            _mainPage.Parts.Add(new SpringFooter());
        }

        public override MainPage GetPage()
        {
            return _mainPage;
        }

    }
    #endregion

    #region summer风格的具体页面及创建器
    public class SummerHeader : Header
    {
        public override void Show()
        {
            Console.WriteLine("Summer风格的header");
        }
    }

    public class SummerBody : Body
    {
        public override void Show()
        {
            Console.WriteLine("Summer风格的body");
        }
    }

    public class SummerFooter : Footer
    {
        public override void Show()
        {
            Console.WriteLine("Summer风格的footer");
        }
    }

    public class SummerBuilder : Builder
    {
        MainPage _mainPage;

        public SummerBuilder()
        {
            _mainPage = new MainPage();
        }

        public override void BuildHeader()
        {
            _mainPage.Parts.Add(new SummerHeader());
        }

        public override void BuildBody()
        {
            _mainPage.Parts.Add(new SummerBody());
        }

        public override void BuildFooter()
        {
            _mainPage.Parts.Add(new SummerFooter());
        }

        public override MainPage GetPage()
        {
            return _mainPage;
        }

    }
    #endregion

我们还是利用反射来解除最终具体类型的依赖:

代码

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="AssemblyName" value="Builder"/>
    <add key="BuilderType" value="Builder.SpringBuilder"/>
  </appSettings>
</configuration>

主程序

代码

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Configuration;

namespace Builder
{
    class Program
    {
        static void Main(string[] args)
        {
            Builder bdr = (Builder)Assembly.Load(ConfigurationManager.AppSettings["AssemblyName"].ToString()).CreateInstance(ConfigurationManager.AppSettings["BuilderType"].ToString());
            PageManager pm = new PageManager(bdr);
            pm.Show();
            Console.Read();
        }
    }

}

 

 

时间: 2024-09-26 07:31:29

温故而知新:设计模式之Builder的相关文章

C#设计模式之建造者设计模式(Builder)

一.建造者(Builder)模式 建造者模式可以将一个产品的内部表象与产品的生成过程分割开来,从而可以使一个建造过程生成具有不同的内部表象的产品对象. 对象性质的建造 有些情况下,一个对象会有一些重要的性质,在它们没有恰当的值之前,对象不能作为一个完整的产品使用.比如,一个电子邮件有发件人地址.收件人地址.主题.内容.附录等部分,而在最起码的收件人地址未被赋值之前,这个电子邮件不能发出. 有些情况下,一个对象的一些性质必须按照某个顺序赋值才有意义.在某个性质没有赋值之前,另一个性质则无法赋值.这

设计模式[20]-Builder

Type: Creational Builder: 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示.是为了将构建复杂对象的过程和它的部件解耦.Builder负责构建部件,Director负责处理构建的过程. #include <iostream> using namespace std; class Part{}; class Product { public: Product(Part* pPartA, Part* pPartB, Part* pPartC){};

温故而知新:设计模式之装饰模式(Decorator)

小时候对日本的动画片十分着迷,"圣斗士"是我的最爱:长大后也曾经一度对"海贼王"十分痴迷:大学看武侠小说时,也特别喜欢那种主人公有奇遇的情况:吃到一颗千年异果,然后功夫大增60年... 这些个场景都有一个共同点:对象(或系统)会因为一些需求(通常这些需求之间没有任何关联),而扩展自己的功能.具体来说:青铜战士如果有幸能穿上黄金圣衣,不管你是不是黄金圣斗士,在穿上黄金圣衣的那一刻,你就具有黄金圣斗士的能力:海赋王中的人物,如果能吃到一颗奇异果,就能获得特别的能力(比如

求教!用Java编写,使用设计模式中Builder模式创建树形菜单,其中要求树形菜单为一个满二叉树

问题描述 输入参数为树的深度.如输入为3则输出以下树形菜单(注意缩进)Level_1Level_2_1Level_3_1_1Level_3_1_2Level_2_2Level_3_2_1Level_3_2_2 解决方案 解决方案二:就这还有用builder模式?是怎么想的?乱用.

温故而知新:设计模式之组合模式(Composite)

场景: 如果想模拟windows的开始菜单,分析一下会发现里面的菜单项:有些有子菜单,有些则没有:因此大体可以将菜单类分为二类,设计代码如下:   /// <summary> /// 菜单的显示接口 /// </summary> public interface IMenu { void Show(); } /// <summary> /// 菜单基类 /// </summary> public class MenuBase { public string

温故而知新:设计模式之原型模式(Prototype)

原型模式个人以为最适合的场景:参照现有的某一个对象实例,快速得到多个完整的实例副本.(通常是深拷贝的副本) 深拷贝在c#中实现的最简单方式莫过于通过反序列化得到一个全新的对象实例.(当然如果浅拷贝的话,方法就很多了,比如利用MemberwiseClone或反射属性自动赋值都可以) 场景:还是游戏场景,就拿三国来说吧,打仗时可能需要小兵若干,每个小兵可能还要骑马...(简单起见其它东东就不提了,比如可能每个小兵还要带兵器若干),这些个实例的数量是动态的, 但是几乎每个小兵的属性都完全相同,每匹战马

温故而知新:设计模式之桥接模式(Bridge)

当一个应用,有着多个维度的变化时,桥模式可将多个维度的变化独立开来(即解耦),最直观的好处就是可有效减少子类的数量. 场景:假如我们要开发一个数据程序程序,导出的数据格式暂定为txt,xml,或直接导入到其它数据库(注:导出格式的需要变化,可以理解为功能维度上的变化),而且我们还要让这套程序能运行于多种平台(windows,linux,freebsd,macos...)上,即跨平台运行(注:可支持多平台的需要变化,可理解为平台需求维度上的变化) 如果按传统思维:每种格式的导出程序都要对应写出N个

温故而知新:设计模式之单件模式(Singleton)

 1 using System; 2  3 namespace Singleton 4 { 5     class Program 6     { 7         static void Main(string[] args) 8         { 9             Singleton s1 = Singleton.Instance;10             Singleton s2 = Singleton.Instance;11 12             Console

温故而知新:设计模式之适配器模式(Adapter)

借用terrylee的原话: Adapter模式主要应用于"希望复用一些现存的类,但是接口又与复用环境要求不一致的情况",在遗留代码复用.类库迁移等方面非常有用. 适配器模式再次体现了"面向接口编程,而非面向实现编程"这一精神. 场景: 有一个基于数据库的系统,里面的数据库操作就拿最常用的查询来说,主要是用SqlHelper类里的QueryData(string sql)这个方法来处理的,后来意外发现该方法实现上性能并不是最好(或者不能满足新的需要),而这时正好有一