zoukankan      html  css  js  c++  java
  • 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);
        }
    }
    
    

    结果:

    胖小人

  • 相关阅读:
    Spring Transaction属性之Propagation
    Eclipse使用代码清理功能(Clean Up)
    JAVA字符串格式化-String.format()的使用
    PHP Windows环境部署
    http server 下载地址
    微信APP支付(Java后台生成签名具体步骤)
    微信APP支付Java后端回调处理
    过滤HTML控件,将输入控件替换成SPAN
    pulic CMS 使用手册
    public cms 配置站点
  • 原文地址:https://www.cnblogs.com/homejim/p/9644182.html
Copyright © 2011-2022 走看看