建造者模式——五种创建型模式之一

作者: lanceJin | 来源:发表于2017-04-27 20:12 被阅读0次

    1.前言


    单例模式可以创建出一个实例,并且这个实例存在的情况下,不会再创建出同样的实例。但是,有个明显的缺点,就是扩展性不高。实际开发中经常会遇到另外一种创建对象的情况,根据用户需求对实例进行设置。若放在构造函数中,要么加判断语句,要么重载构造函数,很不灵活;若通过setter注入,会增加许多与功能不相关的方法,而且对象的设置一般放在初始化时,不能让用户随时修改。

    2.概念


    建造者模式将一个复杂对象的构建与它的表示分离,使得对象专注于功能的展示,隐藏内部的实现。需要注意的是,一旦创建了对象,就不可修改配置了。还有最容易被误解的第二句,同样的构建过程可以创建不同的表示,即创建对象的算法应该独立于它的装配方式,允许创建结果有不同表示。

    3.场景


    食品厂准备生产月饼,需要根据市场喜好制作一套模具。然后,通过模具给月饼胚子成形,表面印上花纹。这里需要注意的是,我们可以新建不同的模具,让食品厂生产不同的月饼。

    4.写法

    public final class Mooncakes {
        
        // 1.创建的对象所具有的属性
        private int mSize;
        private String mName;
        
        private Mooncakes(int size, String name) {
            super();
            mSize = size;
            mName = name;
        }
    
        // 2.创建的对象所表现的功能
        public void product() {
            System.out.println("开始生产  " + mSize + "号大小  " + " " + mName + "花纹的月饼");
        }
        
        public static class Builder {
    
            // 3.构造器存储对象的属性
            private int mSize = 10;
            private String mName = "";
            
            // 4.向构造器设置对象的属性
            public Builder setSize(int size) {
                if (size > 0) {
                    mSize = size;
                }
                return this;
            }
            
            public Builder setName(String name) {
                if (name != null && !name.equals("")) {
                    mName = name;
                }
                return this;
            }
            
            // 5.通过构造器构造对象
            public Mooncakes build() {
                return new Mooncakes(mSize, mName);
            }
            
        }
    
    }
    
    public class Company {
    
        public static void main(String[] args) {
            // 先制作模具,在生产月饼
            new Mooncakes.Builder().setSize(4).setName("嫦娥").build().product();
            new Mooncakes.Builder().setName("嫦娥").build().product();
            new Mooncakes.Builder().setSize(4).build().product();
        }
    
    }
    

    不知道,大家可有发现一个问题。虽然一个具体的模具与一种月饼绑定,但是模具的制作没有规范,比较随意,不符合实际。所以,我们得关注第二点概念。这里有一些误区,大家可以参考happyhippy的文章,看最后的核心思想就够了,毕竟我们讨论的前提是算法不变。Director 定义了模具的制作规范,具体怎么实施由Builder实现类决定。

    // 1.构造复杂对象默认实例
    public class Mooncakes {
        
        private int mSize;
        private String mName;
        
        public Mooncakes() {
            super();
            mSize = 10;
            mName = "";
        }
        
        public void setmSize(int mSize) {
            this.mSize = mSize;
        }
        public void setmName(String mName) {
            this.mName = mName;
        }
    
        @Override
        public String toString() {
            return "Mooncakes [mSize=" + mSize + ", mName=" + mName + "]";
        }
    
    }
    
    // 2.导向器,定义复杂对象的构建算法
    public class Director {
        
        private Builder mBuilder;
        
        public Director(Builder builder) {
            super();
            mBuilder = builder;
        }
    
        // 对于月饼而言,步骤是不会变的,先定型后印花
        public Mooncakes produceMooncakes() {
            return mBuilder.setSize(4).setName("嫦娥").build();
        }
    
    }
    
    // 3.抽象出对象的组装方式
    public abstract class Builder {
        
        protected Mooncakes mCakes = new Mooncakes();
        
        public abstract Builder setSize(int size);
        
        public abstract Builder setName(String name);
        
        public Mooncakes build() {
            return mCakes;
        }
    
    }
    
    // 4.按照正常的方式设置
    public class NormalBuilder extends Builder {
    
        @Override
        public Builder setSize(int size) {
            if (size > 0) {
                mCakes.setmSize(size);
            }
            return this;
        }
    
        @Override
        public Builder setName(String name) {
            if (name != null && !name.equals("")) {
                mCakes.setmName(name);
            }
            return this;
        }
    
    }
    
    // 5.按照我的方式设置
    public class LanceBuilder extends Builder {
    
        @Override
        public Builder setSize(int size) {
            if (size > 0) {
                mCakes.setmSize(size * 2);
            }
            return this;
        }
    
        @Override
        public Builder setName(String name) {
            if (name != null && !name.equals("")) {
                mCakes.setmName("欢乐" + name);
            }
            return this;
        }
    
    }
    
    public class Company{
    
        public static void main(String[] args) {
            // 先制作模具,在生产月饼
            Mooncakes normalCakes = new Director(new NormalBuilder()).produceMooncakes();
            Mooncakes lanceCakes = new Director(new LanceBuilder()).produceMooncakes();
            System.out.println(normalCakes.toString());
            System.out.println(lanceCakes.toString());
        }
    
    }
    

    5.总结


    建造者模式在安卓开发中较为常见,主要是调用系统的控件,比如说Dialog、Notification等需要做大量自定义设置的。由于通过链式调用,使得代码简洁易懂,将封装与扩展很好地结合起来。当然,缺点也很明显,多了不少类。

    相关文章

      网友评论

        本文标题:建造者模式——五种创建型模式之一

        本文链接:https://www.haomeiwen.com/subject/lrhwzttx.html