建造者模式
问题的引入——建造 “小人’
用程序画一个小人,要求小人要有头、身体、两手、两脚。
- 建造“小人”的过程是稳定的,都需要头身手脚。
- 具体建造的细节不同,有胖瘦高矮等区别。
建造小人的第一种方法:
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class Main extends Frame{
public void paint(Graphics g) {
Color c=g.getColor();
g.setColor(Color.BLACK);
g.fillOval(50,50,30,30);//头
g.fillRect(60,80,10,50);//身体
g.drawLine(60,80,40,130);//左手
g.drawLine(70,80,90,130);//右手
g.drawLine(60,130,45,180);//左腿
g.drawLine(70,130,85,180);//左腿
g.setColor(c);
}
public void lauchFrame() {
this.setLocation(400,300);
this.setSize(800,600);
this.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{System.exit(0);}
});
this.setBackground(Color.WHITE);
setVisible(true);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Main person=new Main();
person.lauchFrame();
}
}
建造小人的第二种方法:
//瘦小人类
class PersonThinBuilder{
private Graphics g;
public void PresonThinBuilder(Graphics g) {this.g=g;}
public void build() {
Color c=g.getColor();
g.setColor(Color.BLACK);
g.fillOval(50,50,30,30);//头
g.fillRect(60,80,10,50);//身体
g.drawLine(60,80,40,130);//左手
g.drawLine(70,80,90,130);//右手
g.drawLine(60,130,45,180);//左腿
g.drawLine(70,130,85,180);//左腿
g.setColor(c);
}
}
//胖小人类
class PersonFatBuilder{
private Graphics g;
public void PresonFatBuilder(Graphics g) {this.g=g;}
public void build() {
Color c=g.getColor();
g.setColor(Color.BLACK);
g.fillOval(50,50,30,30);//头
g.fillRect(45,80,40,50);//身体
g.drawLine(60,80,40,130);//左手
g.drawLine(70,80,90,130);//右手
g.drawLine(60,130,45,180);//左腿
g.drawLine(70,130,85,180);//左腿
g.setColor(c);
}
}
public class Main extends Frame {
public void paint(Graphics g) {
PersonFatBuilder p=new PersonFatBuilder();
p.build();
}
public void lauchFrame() {
this.setLocation(400,300);
this.setSize(800,600);
this.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{System.exit(0);}
});
this.setBackground(Color.WHITE);
setVisible(true);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Main person=new Main();
person.lauchFrame();
}
}
这样达到了可以复用这两个画小人程序的目的。但规范化的问题依然没有解决。最好的办法是规定,凡是建造小人,都必须要有头和身体,以及两手两脚。
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
abstract class PersonBuilder{
protected Graphics g;
public PersonBuilder(Graphics g)
{
this.g=g;
}
public abstract void builderHead();
public abstract void builderBody();
public abstract void builderArmLeft();
public abstract void builderArmRight();
public abstract void builderLegLeft();
public abstract void builderLegRight();
}
//画瘦子类继承画人的抽象类
class PersonThinBuilder extends PersonBuilder{
public PersonThinBuilder(Graphics g) {super(g);}
@Override
public void builderHead() {
// TODO Auto-generated method stub
g.fillOval(50, 50, 30, 30);
}
@Override
public void builderBody() {
// TODO Auto-generated method stub
g.fillRect(60, 80, 10, 50);
}
@Override
public void builderArmLeft() {
// TODO Auto-generated method stub
g.drawLine(60, 80, 40, 130);
}
@Override
public void builderArmRight() {
// TODO Auto-generated method stub
g.drawLine(70, 80, 90, 130);
}
@Override
public void builderLegLeft() {
// TODO Auto-generated method stub
g.drawLine(60, 130, 45, 180);
}
@Override
public void builderLegRight() {
// TODO Auto-generated method stub
g.drawLine(70, 130, 85, 180);
}
}
//画胖子类继承画人的抽象类
class PersonFatBuilder extends PersonBuilder{
public PersonFatBuilder(Graphics g) {super(g);}
@Override
public void builderHead() {
// TODO Auto-generated method stub
g.fillOval(50, 50, 30, 30);
}
@Override
public void builderBody() {
// TODO Auto-generated method stub
g.fillRect(45, 80, 40, 50);
}
@Override
public void builderArmLeft() {
// TODO Auto-generated method stub
g.drawLine(60, 80, 40, 130);
}
@Override
public void builderArmRight() {
// TODO Auto-generated method stub
g.drawLine(70, 80, 90, 130);
}
@Override
public void builderLegLeft() {
// TODO Auto-generated method stub
g.drawLine(60, 130, 45, 180);
}
@Override
public void builderLegRight() {
// TODO Auto-generated method stub
g.drawLine(70, 130, 85, 180);
}
}
//控制建造过程的类,隔离用户与建造过程的关联
class PersonDirector{
private PersonBuilder pb;
public PersonDirector(PersonBuilder pb) {
this.pb=pb;
}
public void createPerson() {
pb.builderHead();
pb.builderBody();
pb.builderArmLeft();
pb.builderArmRight();
pb.builderLegLeft();
pb.builderLegRight();
}
}
//客户端代码
public class Main extends Frame{
public void paint(Graphics g) {
Color c=g.getColor();
g.setColor(Color.BLACK);
PersonThinBuilder ptb=new PersonThinBuilder(g);
PersonDirector pdThin=new PersonDirector(ptb);
pdThin.createPerson();
g.setColor(c);
}
public void lauchFrame() {
this.setLocation(400, 300);
this.setSize(800, 600);
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
this.setBackground(Color.WHITE);
setVisible(true);
}
public static void main(String[] args) {
Main drawPerson=new Main();
drawPerson.lauchFrame();
}
}
建造者( Builder)模式
- 如果需要将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示时,需要应用建造者模式( Builder),又叫生成器模式。
- 建造者模式可以将一个产品的内部表示与产品的生产过程分割开来,从而可以使一个建造过程生成具有不同内部表示的产品对象。
- 用了建造者模式,用户就就不需要知道具体建造的过程和细节,只需要指定需要建造的类型就可以得到它们。
- 建造者模式( Builder),将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
建造者模式的基本代码:
import java.util.ArrayList;
import java.util.List;
class Product{
List<String>parts=new ArrayList<String>();
public void Add(String part)//添加产品部件
{
parts.add(part);
}
public void Show()//列举产品部件
{
System.out.println("产品 创建---");
for(String part:parts) {
System.out.println(part);
}
}
}
abstract class Builder{
public abstract void BuilderPartA();
public abstract void BuilderPartB();
public abstract Product GetResult();
}
class ConcreteBuilder1 extends Builder{
private Product product=new Product();
@Override
public void BuilderPartA() {
// TODO Auto-generated method stub
product.Add("部件A");
}
@Override
public void BuilderPartB() {
// TODO Auto-generated method stub
product.Add("部件B");
}
@Override
public Product GetResult() {
// TODO Auto-generated method stub
return product;
}
}
class ConcreteBuilder2 extends Builder{
private Product product=new Product();
@Override
public void BuilderPartA() {
// TODO Auto-generated method stub
product.Add("部件1");
}
@Override
public void BuilderPartB() {
// TODO Auto-generated method stub
product.Add("部件2");
}
@Override
public Product GetResult() {
// TODO Auto-generated method stub
return product;
}
}
class Director{
public void Construct(Builder builder) {
builder.BuilderPartA();
builder.BuilderPartB();
}
}
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Director director=new Director();
Builder b1=new ConcreteBuilder1();
Builder b2=new ConcreteBuilder2();
director.Construct(b1);
Product p1=b1.GetResult();
p1.Show();
director.Construct(b2);
Product p2=b2.GetResult();
p2.Show();
}
}
在什么情况下使用建造者模式
- 相同的方法,不同的执行顺序,产生不同的事件结果时,可以采用建造者模式,需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序。
- 多个部件或零件都可以装配到一个对象中,但是产生的运行结果又不相同时,则可以使用该模式。
- 产品类非常复杂,或者产品类中的调用顺序不同产生了不同的效能,这个时候使用建造者模式是非常合适。
本质:分离整体构建算法和部件构造