• Java设计模式-建造者(Builder)模式


    @

    最近在看Mybatis的源码, 在阅读解析 XML 配置文件的过程中, 发现使用到了建造者(Builder)模式。 因此, 打算重温一下该设计模式。

    由来

    假设我们需要画一个小人, 我们可能会有以下的构造函数定义:

    public Person(HeadType headType, HairType hairType, HairColor hairColor, FaceType faceType, BodyType bodyType, ArmType amrType, LegType legTyype) {
    }
    

    看到这么一个构造函数, 估计我们自己以后回来看的时候都懵了, 这么多参数, 导致我们后续的维护也很麻烦。

    而构造模式就可以解决此类的问题。

    使用

    目标是画一个小人

    1. 定义抽象 Builder

    先定义抽象的PersonBuilder。 该类定义了画小人需要的步骤, 这样每个通过PersonBuilder产生的对象本质上就都是一样的了, 只不过个性上可以不一样。

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

    2. 定义具体 Builder

    在定义一个具体的实现类PersonFatBuilder。 该类继承PersonBuilder, 并实现了抽象方法。

    public class PersonFatBuilder extends PersonBuilder {
        public PersonFatBuilder(Graphics graphics) {
            super(graphics);
        }
        @Override
        public void buildHead() {
            graphics.drawOval(50, 20, 30, 30);
            graphics.drawArc(50, 30, 10, 5, 45, 135);
            graphics.drawArc(70, 30, 10, 5, 45, 135);
            graphics.drawArc(60, 35, 10, 5, 200, 135);
        }
    
        @Override
        public void buildBody() {
            graphics.drawRect(55, 50, 20, 50);
        }
    
        @Override
        public void buildArmLeft() {
            graphics.drawLine(55, 50, 40, 100);
        }
    
        @Override
        public void buildArmRight() {
            graphics.drawLine(75, 50, 90, 100);
        }
    
        @Override
        public void buildLegLeft() {
            graphics.drawLine(55, 100, 45, 150);
        }
    
        @Override
        public void buildLegRight() {
            graphics.drawLine(75, 100, 85, 150);
        }
    }
    
    

    3. 定义具体 Director

    该类负责具体的建造过程, 对建成什么样不关心。

    public class PersonDirector {
        private PersonBuilder personBuilder;
    
        public PersonDirector(PersonBuilder personBuilder) {
            this.personBuilder = personBuilder;
        }
    
        public void drawPerson() {
            personBuilder.buildHead();
            personBuilder.buildBody();
            personBuilder.buildArmLeft();
            personBuilder.buildArmRight();
            personBuilder.buildLegLeft();
            personBuilder.buildLegRight();
        }
    }
    

    4. 测试

    建立一个窗口,将小人画出来。

     public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                // 创建窗口对象
                JFrame frame = new JFrame();
                frame.setVisible(true);
                frame.setTitle("画人");
                frame.setSize(250, 300);
    
                // 设置窗口关闭按钮的默认操作(点击关闭时退出进程)
                frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    
                // 把窗口位置设置到屏幕的中心
                frame.setLocationRelativeTo(null);
                frame.setContentPane(new JPanel(){
                    @Override
                    protected void paintComponent(Graphics g) {
                        super.paintComponent(g);
                        PersonThinBuilder thinBuilder = new PersonThinBuilder(g);
                        PersonDirector director = new PersonDirector(thinBuilder);
                        director.drawPerson();
    
    
                    }
                });
            }
        });
    }
    

    结果如下:

    瘦小人

    定义

    文字定义

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

    换句话解释, 允许你创建不同种类的对象, 同时又能避免对构造函数的污染。当对象有多种类型时, 该模式非常有用。 或者在创建对象时涉及到很多的步骤。

    结构图

    引用《大话设计模式》的一个图

    结构图

    抽象类Builder:为创建Product对象而抽象的接口。

    继承类ConcreateBuilder:具体的建造者, 构造和装配各个部件。

    具体产品类Product:我们需要建造的对象。

    Director: 用来创建产品的, 其内部有Builder类型的成员变量。

    优点

    1. Director 不需要知道 Product 的内部细节, 它只提供需要的信息给建设者, 由具体的建造者ConcreateBuilder处理从而完成产品的构造。
    2. 建造者模式将复杂的产品创建过程分散到了不同的对象中, 从而实现对产品创建过程更精确的控制, 创建过程更加清晰。
    3. 每个具体的建造者都可以创建出完整的产品对象, 而且是相互独立的。 因此, 调用端可以通过不同的具体建造者就可以得到不同的对象。当有新的产品出现时, 不需要改变原有代码, 只需要添加一个建造者即可。

    举例

    现在如果我们想建造一个胖小人,有五官的。那我们只需要添加一个PersonFatBuilder类就可以了, 不需要改原有代码。

    public class PersonFatBuilder extends PersonBuilder {
        public PersonFatBuilder(Graphics graphics) {
            super(graphics);
        }
        @Override
        public void buildHead() {
            graphics.drawOval(50, 20, 30, 30);
            graphics.drawArc(50, 30, 10, 5, 45, 135);
            graphics.drawArc(70, 30, 10, 5, 45, 135);
            graphics.drawArc(60, 35, 10, 5, 200, 135);
        }
    
        @Override
        public void buildBody() {
            graphics.drawRect(55, 50, 20, 50);
        }
    
        @Override
        public void buildArmLeft() {
            graphics.drawLine(55, 50, 40, 100);
        }
    
        @Override
        public void buildArmRight() {
            graphics.drawLine(75, 50, 90, 100);
        }
    
        @Override
        public void buildLegLeft() {
            graphics.drawLine(55, 100, 45, 150);
        }
    
        @Override
        public void buildLegRight() {
            graphics.drawLine(75, 100, 85, 150);
        }
    }
    
    

    结果:

    胖小人

  • 相关阅读:
    Android中Context具体解释 ---- 你所不知道的Context
    JDK6、Oracle11g、Weblogic10 For Linux64Bit安装部署说明
    matplotlib 可视化 —— 定制 matplotlib
    matplotlib 可视化 —— 移动坐标轴(中心位置)
    matplotlib 可视化 —— 移动坐标轴(中心位置)
    matplotlib 可视化 —— 定制画布风格 Customizing plots with style sheets(plt.style)
    matplotlib 可视化 —— 定制画布风格 Customizing plots with style sheets(plt.style)
    指数函数的研究
    指数函数的研究
    指数分布的研究
  • 原文地址:https://www.cnblogs.com/homejim/p/9644182.html
Copyright © 2020-2023  润新知