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


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

    作者: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;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

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

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

    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
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    其中的 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;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    另一种披萨的具体实现 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;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

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

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

    实际应用有非常多,很多组件都提供这样的构造方式,比如 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();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    建造者模式的主要应用

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

    • Spring 中 BeanDefinitionBuilder.getBeanDefinition()方法

    UML 和 代码

    UML 图

    代码

    更多

    设计模式学习专栏

    参考资料

  • 相关阅读:
    CentOS在应用程序菜单中创建快捷方式
    配置hadoop模板虚拟机
    Hive 安装配置
    贪吃蛇项目实践!(下)
    【Redis】set常用命令&集合间操作&内部编码&使用场景
    容联云首发基于统信UOS的Rphone,打造国产化联络中心新生态
    (并查集) 1971. 寻找图中是否存在路径 ——【Leetcode每日一题】
    爬虫----记录某新闻详情页app逆向过程(app逆向初学第一次实战)
    Maven-快速入门教程
    YOLOv5 分类模型 数据集加载 1
  • 原文地址:https://blog.csdn.net/hotonyhui/article/details/127743340