• 设计模式学习(四):建造者模式


    设计模式学习(四):建造者模式

    作者:Grey

    原文地址:

    博客园:设计模式学习(四):建造者模式

    CSDN:设计模式学习(四):建造者模式

    建造者模式

    建造者模式是创建型模式。

    我们在对一个实体类进行属性的 get 或 set 的时候,可以通过封装一些常用的构造方法来简化实体类的构造。

    比如 Effective Java 中举到到这个例子

    // Effective Java 3th examples
    public class NutritionFacts {
        private final int servingSize;
        private final int servings;
        private final int calories;
        private final int fat;
        private final int sodium;
        private final int carbohydrate;
    
        public static class Builder {
            // Required parameters
            private final int servingSize;
            private final int servings;
    
            // Optional parameters - initialized to default values
            private int calories      = 0;
            private int fat           = 0;
            private int sodium        = 0;
            private int carbohydrate  = 0;
    
            public Builder(int servingSize, int servings) {
                this.servingSize = servingSize;
                this.servings    = servings;
            }
    
            public Builder calories(int val) { 
                calories = val;  
                return this;
            }
    
            public Builder fat(int val) { 
               fat = val;   
               return this;
            }
    
            public Builder sodium(int val) { 
               sodium = val;  
               return this; 
            }
    
            public Builder carbohydrate(int val) { 
               carbohydrate = val;  
               return this; 
            }
    
            public NutritionFacts build() {
                return new NutritionFacts(this);
            }
        }
    
        private NutritionFacts(Builder builder) {
            servingSize  = builder.servingSize;
            servings     = builder.servings;
            calories     = builder.calories;
            fat          = builder.fat;
            sodium       = builder.sodium;
            carbohydrate = builder.carbohydrate;
        }
    }
    
    

    其中 Builder 就是一个内部类,用于构造 NutritionFacts 的必要信息,外部调用 NutritionFacts 的构造方法时候,可以这样使用:

    NutritionFacts cocaCola = new NutritionFacts.Builder(240,8).calories(100).sodium(35).carbohydrate(27).build();
    

    image

    构造器模式也适用于类层次结构。抽象类有抽象的 Builder ,具体类有具体的 Builder 。Effective Java中还有一个例子, 假设我们抽象出一个披萨类,各种各样的披萨均可以继承披萨这个抽象类来实现自己的具体类型的披萨。

    Pizza抽象类如下:

    import java.util.*;
    
    // Effective Java 3th examples
    public abstract class Pizza {
        public enum Topping {HAM, MUSHROOM, ONION, PEPPER, SAUSAGE}
        final Set<Topping> toppings;
      
        abstract static class Builder<T extends Builder<T>> {
            EnumSet<Topping> toppings = EnumSet.noneOf(Topping.class);
    
            public T addTopping(Topping topping) {
                toppings.add(Objects.requireNonNull(topping));
                return self();
            }
      
            abstract Pizza build();
      
            // Subclasses must override this method to return "this"
            protected abstract T self();
        }
    
        Pizza(Builder<?> builder) {
            toppings = builder.toppings.clone(); // See Item 50
        }
    }
    
    

    其中的 Builder 方法是抽象的,所以子类需要实现具体的 Builder 策略,

    一种披萨的具体实现 NyPizza

    import java.util.Objects;
    
    public class NyPizza extends Pizza {
        public enum Size {SMALL, MEDIUM, LARGE}
    
        private final Size size;
    
        public static class Builder extends Pizza.Builder<Builder> {
            private final Size size;
    
            public Builder(Size size) {
                this.size = Objects.requireNonNull(size);
            }
    
            @Override
            public NyPizza build() {
                return new NyPizza(this);
            }
    
            @Override
            protected Builder self() {
                return this;
            }
        }
    
        private NyPizza(Builder builder) {
            super(builder);
            size = builder.size;
        }
    }
    

    另一种披萨的具体实现 Calzone

    public class Calzone extends Pizza {
        private final boolean sauceInside;
    
        public static class Builder extends Pizza.Builder<Builder> {
            private boolean sauceInside = false; // Default
    
            public Builder sauceInside() {
                sauceInside = true;
                return this;
            }
    
            @Override
            public Calzone build() {
                return new Calzone(this);
            }
    
            @Override
            protected Builder self() {
                return this;
            }
        }
    
        private Calzone(Builder builder) {
            super(builder);
            sauceInside = builder.sauceInside;
        }
    }
    

    我们在具体调用的时候,可以通过如下方式:

    NyPizza pizza = new NyPizza.Builder(SMALL).addTopping(SAUSAGE).addTopping(ONION).build();
    Calzone calzone = new Calzone.Builder().addTopping(HAM).sauceInside().build();
    

    实际应用有非常多,很多组件都提供这样的构造方式,比如 OkHttp Client 的构造方法:

    public static OkHttpClient create(long connectTimeOut) {
            return new OkHttpClient().newBuilder().connectionSpecs(Arrays.asList(ConnectionSpec.MODERN_TLS, ConnectionSpec.COMPATIBLE_TLS, ConnectionSpec.CLEARTEXT)).connectTimeout(connectTimeOut, TimeUnit.SECONDS).readTimeout(30, TimeUnit.SECONDS).writeTimeout(30, TimeUnit.SECONDS).retryOnConnectionFailure(true).followRedirects(true).followSslRedirects(true).hostnameVerifier((s, sslSession) -> true).cookieJar(new CookieJar() {
                private List<Cookie> cookies;
    
                @Override
                public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
                    this.cookies = cookies;
                }
    
                @Override
                public List<Cookie> loadForRequest(HttpUrl url) {
                    if (cookies != null) {
                        return cookies;
                    }
                    return Collections.emptyList();
                }
            }).build();
        }
    

    建造者模式的主要应用

    • JDK 中的 Calender
    Calendar calendar = new Calendar.Builder().build();
    
    • MyBatis 中 CacheBuilder.build()SqlSessionFactoryBuilder.build()

    • Spring 中 BeanDefinitionBuilder.getBeanDefinition()方法

    UML 和 代码

    UML 图

    代码

    更多

    设计模式学习专栏

    参考资料

  • 相关阅读:
    GAC的理解及其作用 [转]
    Binding Policy in .NET/ Assembly search order (Bin/GAC)
    Batch update
    Table-Valued Parameters in SQL Server 2008 (ADO.NET)
    EXT的bug 布局border 和 grid的cellediting
    ext 的controller中的refs的使用方法
    Ext 修改内容之后 不做任何动作 再次修改时的数据是原来第一次修改前的数据
    php 与mysql 数据库
    前端开发和后端开发
    http 你造吗?
  • 原文地址:https://www.cnblogs.com/greyzeng/p/16868456.html
Copyright © 2020-2023  润新知