建造者模式

在讲述这个模式之前,我们先看一个案例:建造小人(只需要建造的小人有头、身子、四肢即可)

public class DrawPeople extends JFrame {
    //DrawSee构造方法
    public DrawPeople() {
        setBounds(0, 0, 500, 500);//窗体起始位置
        setVisible(true);//窗体是否可见
        setLayout(null); //窗体布局  
        setResizable(false);//窗体是否可进行拖动设置大小
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);        
        
        try {
            Thread.sleep(500);
        } catch (Exception e) {
            e.printStackTrace();
        }        
        // 获取专门用于在窗口界面上绘图的对象
        Graphics  jg =  this.getGraphics();
        
        // 绘制区域
        paintComponents(jg);
    }
    
    
    //画一个人
    public void paintComponents(Graphics g) {
        try {
            g.drawArc(150, 50, 30, 30, 0, 360);//画头
            g.drawArc(145, 80, 40, 50, 0, 360);//画身子
            g.drawLine(150, 80, 130, 130);
            g.drawLine(180, 80, 200, 130);
            g.drawLine(160, 130, 145, 180);
            g.drawLine(170, 130, 185, 180);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

测试方法
public class Test {
     public static void main(String[] args) {   
            new DrawPeople();
     }   
}

绘制结果如下图所示

那我现在需要绘制一个比较瘦的人,怎么办?

正常程序员都会想:这还不简单,把这个类复制一份,把绘制参数改下不就行了。

那万一复制的时候少复制了一行,让小人缺胳膊少腿怎么办?

这对一个人来说可是巨大的损失,谁都不想让身体残缺不全。这个问题怎么解决呢?

下面介绍建造者模式:http://www.runoob.com/design-pattern/builder-pattern.html

将一个复杂对象的构建与他的表示分离,使得同样的构建过程可以创建不同的表示。

那怎么用建造者模式呢?

以画小人为例,我们需要画头、身体、左手、右手、左脚、右脚,所以我们先定义一个抽象的建造人的类,把这个过程稳定住,不让任何人遗忘当中的任何一步。

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

然后我们需要建造一个胖的人,就让这个胖子类取继承这个抽象类,那就必须去重写这些抽象方法了,否则编译器也不让你通过。

public class PersonFatBuilder extends JFrame implements PersonBuilder{

    private Graphics  g;

    public PersonFatBuilder() {
        setBounds(0, 0, 500, 500);//窗体起始位置
        setVisible(true);//窗体是否可见
        setLayout(null); //窗体布局  
        setResizable(false);//窗体是否可进行拖动设置大小
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);        
        
        try {
            Thread.sleep(500);
        } catch (Exception e) {
            e.printStackTrace();
        }        
        // 获取专门用于在窗口界面上绘图的对象
        this.g =  this.getGraphics();
        
        // 绘制游戏区域
        paintComponents(this.g);
    }

    @Override
    public void buildHead() {
        g.drawArc(150, 50, 30, 30, 0, 360);//画头
    }

    @Override
    public void buildBody() {
        g.drawArc(145, 80, 40, 50, 0, 360);//画身子
    }

    @Override
    public void buildArmLeft() {
        g.drawLine(150, 80, 130, 130);
    }

    @Override
    public void buildArmRight() {
        g.drawLine(180, 80, 200, 130);
    }

    @Override
    public void buildLegLeft() {
        g.drawLine(160, 130, 145, 180);
    }

    @Override
    public void buildLegRight() {
        g.drawLine(170, 130, 185, 180);
    }
}

瘦子类也是用类似的代码去实现这个类就可以了。

但现在只是保证胖子类拥有了头身手脚方法,但依然无法保证这些方法一定会被调用,怎么办?

我们还缺少建造者模式中一个重要的类,指挥者(Director),用它来控制建造过程,也用它来隔离用户与建造过程的关联。

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 Test {
    public static void main(String[] args) {
        PersonFatBuilder pfb = new PersonFatBuilder();
        PersonDirector pd = new PersonDirector(pfb);
        pd.createPerson();
    }
}

PersonDirector类的目的就是根据用户的选择来一步步建造小人,而建造的过程在指挥者这里完成,用户就不需要知道了,而且,每个建造过程都是一定要做的,保证了建造流程的正确性,这样,缺胳膊少腿的情况就不会出现了。

做个比喻:Builder像是图纸,PersonFatBuilder是具体的施工人员,PersonDirector就是个监工,保证施工过程正确有序。

原文地址:https://www.cnblogs.com/jwen1994/p/10116245.html