前言:
建造者模式(Builder Pattern)是将一个复杂对象的的构建和它的表示分离,使得同样的构建过程可以创建么不同的表示。
一.建造者模式简介:
建造者模式(Builder Pattern)是为解决在软件系统中,对一个复杂对象的创建过程和算法进行封装,隐藏该对象是如何组装的。该模式又称为生成器模式。
二.建造者模式的实例讲解:
案例:通过建造者模式,绘制不同风格人物图像。
1.产品设计UML类图:
(图片加载慢,多刷新几下,耐心等待……)
注:指挥者类PersonDirector
和建造者抽象类PersonBuilder
的是聚合关系。
聚合关系:表示一种弱的拥有关系,体现的是A对象可以包含B对象,但B对象不是A对象的一部分。
2.建造者抽象类:
设计分析:所需要绘制的人物,都有共同的特征,比如人都有手有脚。将这些共同的特征抽象为一个抽象接口,用来封装绘制人物的过程,让子类不会丢失任何的步骤。
package com.pattern.builder.buider;
import java.awt.Graphics;
public abstract class PersonBuilder {
protected Graphics graphics;//绘图
public PersonBuilder(Graphics graphics) {
super();
this.graphics = graphics;
}
public PersonBuilder() {
}
//绘制头部
public abstract void BuildHead();
//绘制身体
public abstract void BuildBody();
//绘制左臂
public abstract void BuildArmLeft();
//绘制右臂
public abstract void BuildArmRight();
//绘制左腿
public abstract void BuildLegLeft();
//绘制右腿
public abstract void BuildLegRight();
}
3.绘制具体人物类:
设计分析: 继承建造者抽象类,并且实现父类的建造人物过程。
①绘制一个胖子类:
package com.pattern.builder.buider;
import java.awt.Graphics;
public class FatPersonBuilder extends PersonBuilder {
public FatPersonBuilder(Graphics graphics) {
super(graphics);
}
public FatPersonBuilder() {
super();
}
@Override
public void BuildHead() {
graphics.drawOval(315, 70, 30, 30);
}
@Override
public void BuildBody() {
graphics.drawRect(305, 100, 50, 30);
}
@Override
public void BuildArmLeft() {
graphics.drawLine(305, 100, 275, 120);// 左臂
}
@Override
public void BuildArmRight() {
graphics.drawLine(355, 100, 380, 120);// 右臂
}
@Override
public void BuildLegLeft() {
graphics.drawLine(305, 130, 275, 150);// 左腿
}
@Override
public void BuildLegRight() {
graphics.drawLine(355, 130, 380, 150);// 右腿
}
public static void main(String[] args) {
FatPersonBuilder thinPersonBuilder = new FatPersonBuilder();
thinPersonBuilder.BuildHead();
}
}
②绘制一个瘦子类:
package com.pattern.builder.buider;
import java.awt.Graphics;
public class ThinPersonBuilder extends PersonBuilder {
public ThinPersonBuilder(Graphics graphics) {
super(graphics);
}
public ThinPersonBuilder() {
super();
}
@Override
public void BuildHead() {
graphics.drawOval(100, 70, 30, 30);
}
@Override
public void BuildBody() {
graphics.drawRect(105, 100, 20, 30);
}
@Override
public void BuildArmLeft() {
graphics.drawLine(105, 100, 75, 120);// 左臂
}
@Override
public void BuildArmRight() {
graphics.drawLine(125, 100, 150, 120);// 右臂
}
@Override
public void BuildLegLeft() {
graphics.drawLine(105, 130, 75, 150);// 左腿
}
@Override
public void BuildLegRight() {
graphics.drawLine(125, 130, 150, 150);// 右腿
}
public static void main(String[] args) {
ThinPersonBuilder thinPersonBuilder = new ThinPersonBuilder();
thinPersonBuilder.BuildHead();
}
}
4.指挥者类
设计分析: 指挥者类是用来控制建造过程,用它来隔离用户与建造过程的关联。
在本例中,指挥者类可以控制绘制一个人物的过程,可以对过程进行自由调整。如果新增一个绘画产品“绘制残疾人画像”(如:没有右臂的杨过),则不需要改动具体的构造者类,只需要在指挥者中,新增一个绘制残疾人物画像的方法,将绘制“右臂”的过程去掉即可。这就是指挥者的一个用途。
package com.pattern.builder.director;
import com.pattern.builder.buider.PersonBuilder;
/**
* 指挥者类:控制建造过程
*
* @author 葫芦娃
*
*/
public class PersonDirector {
private PersonBuilder pb; // 依赖建造者的抽象类对象
public PersonDirector(PersonBuilder pb) {
super();
this.pb = pb;
}
// 绘制人物
public void creatPerson() {
pb.BuildHead();
pb.BuildBody();
pb.BuildArmLeft();
pb.BuildArmRight();
pb.BuildLegLeft();
pb.BuildLegRight();
}
}
5.客户端中使用:
设计分析: 客户端需要依赖指挥着类和具体的建造者类,通过指挥者中的方法,控制建造者绘制具体的人物画像,使得建造者类中的代码和客户端的表示层代码分离,降低耦合度。
注:本客户端用到Java
的Swing
绘图,若不了解如何用Java
绘图,请点击参考本人另一篇博文介绍《 Java用JFrame、JPanel、Graphics绘图案例讲解》。
package com.pattern.builder.client;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import com.pattern.builder.buider.FatPersonBuilder;
import com.pattern.builder.buider.ThinPersonBuilder;
import com.pattern.builder.director.PersonDirector;
public class Client {
public static void main(String[] args) {
// 创建相框
JFrame jFrame = new JFrame();
// 创建画板
JPanel jpanel = new JPanel() {
// 序列号(可省略)
private static final long serialVersionUID = 1L;
// 重写paint方法
@Override
public void paint(Graphics graphics) {
super.paint(graphics);
// 瘦子建造者
ThinPersonBuilder thinPersonBuilder = new ThinPersonBuilder(graphics);
// 指挥者,根据需求构建小人对象
PersonDirector personDirectorThin = new PersonDirector(thinPersonBuilder);
// 根据需求选择过程中的步骤,执行或者跳过
personDirectorThin.creatPerson();
// 胖子建造者
FatPersonBuilder fatPersonBuilder = new FatPersonBuilder(graphics);
// 指挥者,根据需求构建小人对象
PersonDirector personDirectorFat = new PersonDirector(fatPersonBuilder);
// 根据需求选择过程中的步骤,执行或者跳过
personDirectorFat.creatPerson();
}
};
// 将绘有小人图像的画板嵌入到相框中
jFrame.add(jpanel);
// 将画框展示出来。true设置可见,默认为false隐藏
jFrame.setVisible(true);
// 设置画框大小(宽度,高度),默认都为0
jFrame.setSize(500, 300);
}
}
6.运行结果展示:
(图片加载慢,多刷新几下,耐心等待……)
7.源码下载
本文示例代码下载地址:点击下载
三.总结:
1.建造者模式的优点:
- 隐藏创建复杂对象细节。创建复杂的对象的时候,使得建造代码和表示代码分离,隐藏建造者对产品过程的组装。
- 方便扩展。新增一个产品只需要新增一个具体的建造者就可以了。
2.建造者模式的缺点:
- 当具体产品的细节不同的时候,建造者模式就不适用了。
- 每次产品扩展,都要新增一个具体的建造者类,增大了代码量。