C#学习笔记-建造者模式
题目:用程序画一个小人。
实现:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
} private void button1_Click(object sender, EventArgs e)
{
Pen p = new Pen(Color.Yellow);
Graphics gThin = pictureBox1.CreateGraphics(); gThin.DrawEllipse(p, , , , );
gThin.DrawRectangle(p, , , , );
gThin.DrawLine(p, , , , );
gThin.DrawLine(p, , , , );
gThin.DrawLine(p, , , , );
gThin.DrawLine(p, , , , ); Graphics gFat = pictureBox2.CreateGraphics(); gFat.DrawEllipse(p, , , , );
gFat.DrawEllipse(p, , , , );
gFat.DrawLine(p, , , , );
gFat.DrawLine(p, , , , );
gFat.DrawLine(p, , , , );
gFat.DrawLine(p, , , , );
}
}
效果截图:

题目延伸1:将画小人的部分与界面分离开,不让界面的代码显得冗长,也为了防止其他地方调用画小人的情况出现。
解析:
直接将画小人挪到单独的类里即可
PersonBuilder类:
class PersonThinBuilder
{
protected Graphics g;
protected Pen p;
public PersonThinBuilder(Graphics g,Pen p)
{
this.g = g;
this.p = p;
} public void Build()
{
g.DrawEllipse(p, , , , );
g.DrawRectangle(p, , , , );
g.DrawLine(p, , , , );
g.DrawLine(p, , , , );
g.DrawLine(p, , , , );
g.DrawLine(p, , , , );
}
}
class PersonFatBuilder
{
protected Graphics g;
protected Pen p; public PersonFatBuilder(Graphics g, Pen p)
{
this.g = g;
this.p = p;
} public void Build()
{
g.DrawEllipse(p, , , , );
g.DrawEllipse(p, , , , );
g.DrawLine(p, , , , );
g.DrawLine(p, , , , );
g.DrawLine(p, , , , );
g.DrawLine(p, , , , );
}
}
主函数:
private void button1_Click(object sender, EventArgs e)
{
Pen p = new Pen(Color.Yellow);
Graphics gThin = pictureBox1.CreateGraphics();
PersonThinBuilder ptb = new PersonThinBuilder(gThin, p);
ptb.Build(); Graphics gFat = pictureBox2.CreateGraphics();
PersonFatBuilder pfb = new PersonFatBuilder(gFat, p);
pfb.Build();
}
题目延伸2:上面实现了将胖的小人和瘦的小人分别画出来,但是很可能出现,如果当前需要画的人物过多,很可能出现缺胳膊少腿的尴尬情况,考虑到人的组成部分都一致,再细致一下代码。
实现:
abstract class PersonBuilder
{
protected Graphics g;
protected Pen p; public PersonBuilder(Graphics g,Pen p)
{
this.p = p;
this.g = g;
}
//将手、脚、身体分开写,就保证了不会忘却画某一个部分
public abstract void BuildHead();
public abstract void BuildBody();
public abstract void BuildArmLeft();
public abstract void BuildArmRight();
public abstract void BuildLegLeft();
public abstract void BuildLegRight();
}
/// <summary>
/// 继承于PersonBuilder类
/// 必须全部重写PersonBuilder类里的抽象方法
/// 这样保证了在画图的时候不会出现“缺胳膊少腿”的现象
/// </summary>
class PersonThinBuilder : PersonBuilder
{
public PersonThinBuilder(Graphics g, Pen p) : base(g, p)
{
} public override void BuildHead()
{
g.DrawEllipse(p, , , , );
}
public override void BuildBody()
{
g.DrawRectangle(p, , , , );
}
public override void BuildArmLeft()
{
g.DrawLine(p, , , , );
}
public override void BuildArmRight()
{
g.DrawLine(p, , , , );
}
public override void BuildLegLeft()
{
g.DrawLine(p, , , , );
}
public override void BuildLegRight()
{
g.DrawLine(p, , , , );
}
}
class PersonFatBuilder : PersonBuilder
{
public PersonFatBuilder(Graphics g, Pen p) : base(g, p)
{ } public override void BuildHead()
{
g.DrawEllipse(p, , , , );
}
public override void BuildBody()
{
g.DrawEllipse(p, , , , );
}
public override void BuildArmLeft()
{
g.DrawLine(p, , , , );
}
public override void BuildArmRight()
{
g.DrawLine(p, , , , );
}
public override void BuildLegLeft()
{
g.DrawLine(p, , , , );
}
public override void BuildLegRight()
{
g.DrawLine(p, , , , );
}
}
/// <summary>
/// 客户端调用的时候是不需要知道头身手脚这些方法的
/// 所以我们需要一个很重要的类,指挥者(Director)
/// 用它来控制建造过程,也隔离开了用户与建造过程的关联
/// </summary>
class PersonDirector
{
private PersonBuilder pb;
public PersonDirector(PersonBuilder pb)
{
this.pb = pb;
}
public void CreatePerson()
{
pb.BuildHead();
pb.BuildBody();
pb.BuildArmLeft();
pb.BuildArmRight();
pb.BuildLegLeft();
pb.BuildLegRight();
}
}
解析:
这里用到的就是建造者模式(Builder),将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
它主要是用于创建一些复杂的对象,这些对象的内部构建间的建造顺序通常是稳定的,蛋对象内部的构建通常面临着复杂的变化。
建造者模式的好处就是使得建造代码与表示代码分离,由于建造者隐藏了该产品是如何组装的,所以若需要改变一个产品的内部表示,只需要定义一个具体的建造者就可以了。
附:再次简化主函数部分
实现:
PersonBuilder类:
abstract class PersonBuilder
{
protected Graphics g;
protected Pen p; public PersonBuilder(Graphics g, Pen p)
{
this.g = g;
this.p = p;
} public abstract void BuildHead();
public abstract void BuildBody();
public abstract void BuildArmLeft();
public abstract void BuildArmRight();
public abstract void BuildLegLeft();
public abstract void BuildLegRight();
} class PersonThinBuilder : PersonBuilder
{
public PersonThinBuilder(Graphics g, Pen p)
: base(g, p)
{ } public override void BuildHead()
{
g.DrawEllipse(p, , , , );
} public override void BuildBody()
{
g.DrawRectangle(p, , , , );
} public override void BuildArmLeft()
{
g.DrawLine(p, , , , );
} public override void BuildArmRight()
{
g.DrawLine(p, , , , );
} public override void BuildLegLeft()
{
g.DrawLine(p, , , , );
} public override void BuildLegRight()
{
g.DrawLine(p, , , , );
}
} class PersonFatBuilder : PersonBuilder
{
public PersonFatBuilder(Graphics g, Pen p)
: base(g, p)
{ } public override void BuildHead()
{
g.DrawEllipse(p, , , , );
} public override void BuildBody()
{
g.DrawEllipse(p, , , , );
} public override void BuildArmLeft()
{
g.DrawLine(p, , , , );
} public override void BuildArmRight()
{
g.DrawLine(p, , , , );
} public override void BuildLegLeft()
{
g.DrawLine(p, , , , );
} public override void BuildLegRight()
{
g.DrawLine(p, , , , );
}
} class PersonDirector
{
private PersonBuilder pb;
/**
* Assembly=>程序集
*/
public PersonDirector(string type,Graphics g,Pen p)
{
string assemblyName = "建造者模式03";
object[] args = new object[];
args[] = g;
args[] = p; //Assembly.CreateInstance 方法 (String, Boolean, BindingFlags, Binder, Object[], CultureInfo, Object[])
//从此程序集中查找指定的类型,并使用系统激活器创建它的实例,包括可选的区分大小写搜索并具有指定的区域性、参数和绑定及激活属性。
//public object CreateInstance(string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder binder, object[] args, CultureInfo culture, object[] activationAttributes)
this.pb = (PersonBuilder)Assembly.Load(assemblyName).CreateInstance(assemblyName + ".Person" + type + "Builder", false, BindingFlags.Default, null, args, null, null);
/**
* typeName
* 要查找的类型的 Type.FullName。
* ignoreCase
* 如果为 true,则忽略类型名的大小写;否则,为 false。
* bindingAttr
* 影响执行搜索的方式的位屏蔽。此值是 BindingFlags 中的位标志的组合。
* binder
* 一个启用绑定、参数类型强制、成员调用以及通过反射进行 MemberInfo 对象检索的对象。如果 binder 为 空引用(在 Visual Basic 中为 Nothing),则使用默认联编程序。
* args
* Object 类型的数组,包含要传递给构造函数的参数。此参数数组在数量、顺序和类型方面必须与要调用的构造函数的参数匹配。如果需要默认的构造函数,则 args 必须是空数组或 空引用(在 Visual Basic 中为 Nothing)。
* culture
* 用于控制类型强制的 CultureInfo 的实例。如果这是 空引用(在 Visual Basic 中为 Nothing),则使用当前线程的 CultureInfo。(例如,这对于将表示 1000 的 String 转换为 Double 值是必需的,因为不同的区域性以不同的方式表示 1000。)
* activationAttributes
* Object 类型的数组,包含一个或多个可以参与激活的激活属性。激活属性的一个示例是: URLAttribute
*
* 返回值
* 表示此类型且匹配指定条件的 Object 的实例;如果没有找到 typeName,则为 空引用(在 Visual Basic 中为 Nothing)。
*/
}
public void CreatePerson()
{
pb.BuildHead();
pb.BuildBody();
pb.BuildArmLeft();
pb.BuildArmRight();
pb.BuildLegLeft();
pb.BuildLegRight();
}
}
主函数:
private void button1_Click(object sender, EventArgs e)
{
Pen p = new Pen(Color.Yellow);
Graphics gThin = pictureBox1.CreateGraphics(); PersonDirector pdThin = new PersonDirector("Thin", gThin, p);
pdThin.CreatePerson(); Graphics gFat = pictureBox2.CreateGraphics(); PersonDirector pdFat = new PersonDirector("Fat", gFat, p);
pdFat.CreatePerson();
}
注:文中所有代码及知识点均来自于《大话设计模式》,本人属于边学边看边敲代码边总结的阶段。
C#学习笔记-建造者模式的更多相关文章
- 学习笔记——建造者模式Builder
构造者模式.外部场景如果需要一个汽车类,它不需要关心如何构造,它只需要告诉Director需要什么,就可以从Director获得. 如:CDirector(IBuilder* aBuilder); 场 ...
- Java-马士兵设计模式学习笔记-建造者模式
一.概述 二.代码 1.Animal.java public interface Animal { public void bark(); } 2.Dog.java public class Dog ...
- 《Head first设计模式》学习笔记 – 迭代器模式
<Head first设计模式>学习笔记 – 迭代器模式 代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示. 爆炸性新闻:对象村餐厅和对象村煎饼屋合并了!真是个 ...
- Java设计模式学习记录-建造者模式
前言 今天周末,有小雨,正好也不用出门了,那就在家学习吧,经过了两周的面试,拿到了几个offer,但是都不是自己很想去的那种,要么就是几个人的初创小公司,要么就是开发企业内部系统的这种传统开发,感觉这 ...
- 设计模式学习之建造者模式(Builder,创建型模式)(6)
假如我们需要建造一个房子,并且我们也不知道如何去建造房子,所以就去找别人帮我们造房子 第一步: 新建一个房子类House,里面有房子该有的属性,我们去找房子建造者接口HouseBuilder,我们要建 ...
- 《精通Python设计模式》学习之建造者模式
这种模式,就是将一个最终对象分级分层建造出来. 在软件发布过程中,不同的JAVA,PYTHON,NODE.JS,ZIP压缩包, 就可以使用不同的阶段来使用建造者模式的. from enum impor ...
- C# 设计模式巩固笔记 - 建造者模式
前言 写给自己-贵在坚持.建造者模式不复杂,但是想个形象的例子好难. 介绍-建造者模式 定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 实现 建造者模式主要是应对复杂 ...
- 设计模式之笔记--建造者模式(Builder)
建造者模式(Builder) 定义 建造者模式(Builder),将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 类图 描述 Builder:定义一个建造者抽象类,以规范产 ...
- 学习笔记——解释器模式Interpreter
解释器模式,其实就是编译原理中的语法解释器,如果用在项目中,可以用于实现动态脚本的解析,也就是说项目可以支持用户脚本扩展. 但实际上,这种运行时解释,效率很慢,如果不是很需要的话,不建议使用. 一种简 ...
随机推荐
- 基于ASP.MVC票据FormsAuthenticationTicket身份认证
做一个最基础的业务需求用户登录,将此用户的身份发回到客户端的Cookie,之后此用户再访问这个web应用就会连同这个身份Cookie一起发送到服务端.服务端上的授权设置就可以根据不同目录对不同用户的访 ...
- gulp管理静态资源缓存
前端项目在版本迭代的时候,难免会遇到静态缓存的问题,明明开发的是ok的,但是一部署到服务器上,发现页面变得乱七八糟,这是由于静态缓存引起的. 从上面这张图片可以看出,浏览器加载css,js等资源时,s ...
- Azure: 给 ubuntu 虚机挂载数据盘
在 azure 上创建的虚机默认会分配两个磁盘,分别是系统盘和一个临时磁盘.如果我们要在系统中安装使用 mysql 等软件,需要再创建并挂载单独的数据盘用来保存数据库文件.这是因为临时磁盘被定义为:用 ...
- 项目实战12.1—企业级监控工具应用实战-zabbix安装与基础操作
无监控,不运维.好了,废话不多说,下面都是干货. 警告:流量党勿入,图片太多!!! 项目实战系列,总架构图 http://www.cnblogs.com/along21/p/8000812.html ...
- MongodDB学习笔记(二)(复制)
mongoDB的复制非常容易配置,其实现有两种方式,一种是主从复制,一种是复制集,前者的好处是容易配置,但是如果主服务器宕掉了,整个系统就崩溃了,后者的好处是如果主服务器宕掉了,其他服务器会通过投票选 ...
- C++ 头文件系列(iostream)
1. 简介 这个头文件非常特殊,它只声明了8个常用流对象. 2. 8个对象 2.1 窄字符对象(char) extern istream cin extern ostream cout extern ...
- 10本Java书籍推荐
1. <深入理解Java虚拟机>是近年来国内出版的唯一一本与Java虚拟机相关的专著,也是唯一一本同时从核心理论和实际运用这两个角度去探讨Java虚拟机的著作,不仅理论分析得透彻,而且书中 ...
- su和sudo命令的区别
一. 使用 su 命令临时切换用户身份 参考 1.su 的适用条件和威力 su命令就是切换用户的工具,怎么理解呢?比如我们以普通用户beinan登录的,但要添加用户任务,执行useradd ,bein ...
- centos7 系统安装问题汇总
centos7 系统安装问题汇总: 1.使用u盘 安装centos7时,一直提示:'.../dev/root does not exist,could not boot' 解决方法: 2.不能将原来 ...
- Eclipse配置tomcat程序发布到哪里去了?
今天帮同事调一个问题,明明可以main函数执行的,他非要固执的使用tomcat执行,依他.但是发布到tomcat之后我想去看看发布后的目录,所以就打开了tomcat中的webapps目录,可是并没有发 ...