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(); } } }