引入
用笔画一个个小人,形状各异,要求小人有胳膊、身体、头部、手脚就可以。但是直接这样去编程有时候会因为疏忽忘记,出现缺手缺脚的情况,就说明这种建造方式不是稳定的。
一、定义
建造者模式(Builder)将一个复杂对象的创建和它的表示方法分离,使得同样的构建过程可以创建不同的表示。
二、组成:
1、Product产品类:具体产品
2、Builder抽象建造者:为了建造一个Product对象的各个部件指定的抽象接口。
3、ConcreteBuilder具体建造者:实现Builder接口,构造和装配各个部件。
4、Director导演类:构建一个Builder接口对象。
UML类图:
建造者模式基本代码:
Product类——产品类,有由多个部件组成
public class Product {
List<String> parts=new ArrayList<String>();
public void Add(String part){
parts.add(part);
}
public void display(){
System.out.println("\n产品创建");
for(String s: parts){
System.out.println(s);
}
}
}
Builder类——抽象建造者,确定产品由两个部件A和B组成,并声明一个得到产品建造后结果的方法getProduct.
public abstract class Builder {
public abstract void buildPartA();
public abstract void buildPartB();
public abstract Product getProduct();
}
ConcereteBuilder1——具体建造者类
public class ConcreteBuilder1 extends Builder {
private Product product=new Product();
@Override
public void buildPartA() {
product.Add("部件A");
}
@Override
public void buildPartB() {
product.Add("部件B");
}
public Product getProduct() {
return product;
}
}
ConcereteBuilde2——具体建造者类
public class ConcreteBuilder2 extends Builder {
private Product product=new Product();
@Override
public void buildPartA() {
product.Add("部件C");
}
@Override
public void buildPartB() {
product.Add("部件D");
}
public Product getProduct() {
return product;
}
}
Director类——指挥者类。
public class Director {
public void ConStruct(Builder builder){
builder.buildPartA();
builder.buildPartB();
}
}
测试类
public class Demo {
public static void main(String[] args) {
Director director = new Director();
Builder b1 = new ConcreteBuilder1();
Builder b2 = new ConcreteBuilder2();
director.ConStruct(b1);
b1.getProduct().display();
director.ConStruct(b2);
b2.getProduct().display();
}
}
三、具体场景示例(画火柴人)
1、GUI绘图的相关 Java类介绍:
- JFrame类,是Java图形用户界面(GUI)工具包swing中的存放组件的容器。相当于相框。
- JPanel类,是Java图形用户界面(GUI)工具包swing中的面板容器类。相当于画板。
- Graphics类,是Java用于绘图和显示格式化文字的工具。相当于画笔。
2、代码实现
抽象建造者PersonBuilder类
public abstract class PersonBuilder {
protected Graphics graphics;
public PersonBuilder(Graphics graphics) {
this.graphics = graphics;
}
public abstract void BuildHead();
public abstract void BuildBody();
public abstract void BuildArmLeft();
public abstract void BuildArmRight();
public abstract void BuildLegLeft();
public abstract void BuildLegRight();
}
具体建造者类PersonJumpBuilder
/**
* 跳跃的火柴人
*/
public class PersonJumpBuilder extends PersonBuilder {
public PersonJumpBuilder(Graphics graphics) {
super(graphics);
}
@Override
public void BuildHead() {
// 头部
graphics.fillOval(100, 70, 30, 30);
}
@Override
public void BuildBody() {
// 身体
graphics.drawLine(115, 100, 115, 140);
}
@Override
public void BuildArmLeft() {
// 左臂
graphics.drawLine(115, 105, 70, 90);
}
@Override
public void BuildArmRight() {
// 右臂
graphics.drawLine(115, 105, 160, 90);
}
@Override
public void BuildLegLeft() {
// 左腿
graphics.drawLine(115, 140, 55, 150);
}
@Override
public void BuildLegRight() {
// 右腿
graphics.drawLine(115, 140, 175, 150);
}
}
具体建造者类PersonRunBuilder
/**
* 奔跑的火柴人
*/
public class PersonRunBuilder extends PersonBuilder {
public PersonRunBuilder(Graphics graphics) {
super(graphics);
}
@Override
public void BuildHead() {
// 头部
graphics.fillOval(100, 70, 30, 30);
}
@Override
public void BuildBody() {
// 身体
graphics.drawLine(115, 95, 100, 160);
}
@Override
public void BuildArmLeft() {
// 左臂
graphics.drawLine(115, 105, 95, 105);
graphics.drawLine(95, 105, 85, 130);
}
@Override
public void BuildArmRight() {
// 右臂
graphics.drawLine(115, 105, 125, 130);
graphics.drawLine(125, 130, 150, 130);
}
@Override
public void BuildLegLeft() {
// 左腿
graphics.drawLine(95, 160, 70, 160);
}
@Override
public void BuildLegRight() {
// 右腿
graphics.drawLine(105, 140, 120, 150);
graphics.drawLine(120, 150, 120, 190);
}
}
指挥者类PersonDirector
public 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();
}
}
测试类
public class Demo {
public static void main(String[] args) {
// 创建窗口对象
JFrame frame = new JFrame();
frame.setVisible(true);
frame.setTitle("画人");
frame.setSize(280, 300);
// 设置窗口关闭按钮的默认操作(点击关闭时退出进程)
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// 把窗口位置设置到屏幕的中心
frame.setLocationRelativeTo(null);
frame.setContentPane(new JPanel(){
protected void paintComponent(Graphics g) {
super.paintComponent(g);
BasicStroke stokeLine = new BasicStroke(6.0f);
Graphics2D g2=(Graphics2D) g;
g2.setStroke(stokeLine);
PersonBuilder pb = new PersonRunBuilder(g2);
/*PersonBuilder pb = new PersonJumpBuilder(g2);*/
PersonDirector director = new PersonDirector(pb);
director.createPerson();
}
});
}
}
效果展示
四、模式用途
当我们需要将一个复杂的对象的构建与它的表示分离,是的同样的构建过程可以创建不同的表示,需要使用到建造者模式。它将产品的内部表象与产品的生成过程分割开来,从而可以使得一个构造过程声称具有不同的内部表象的产品。因此用户只需要指定需要构造的类型就可以得到他们,而具体的构造过程和细节就不需要知道了。同时也满足开闭原则,若需改变产品外观,只需要在定义一个具体建造者类就可以了。