• Builder设计模式--改善构造器多个参数时可显著改善可读性


      作为一名程序开发者,设计模式其实一直有在接触,只是没有专门的去学过,所以可能对设计模式没有一个系统的理解。在一次项目中,需要使用到第三方服务商提供的功能,为了尽快的熟悉其功能代码,在官网下了demo来研究其功能实现,发现一个用来封装消息通知的类是这样写的:

      1 package cn.jpush.api.push.model.notification;
      2 
      3 import cn.jpush.api.push.model.PushModel;
      4 import cn.jpush.api.utils.Preconditions;
      5 import com.google.gson.JsonElement;
      6 import com.google.gson.JsonObject;
      7 import com.google.gson.JsonPrimitive;
      8 
      9 import java.util.HashSet;
     10 import java.util.Map;
     11 import java.util.Set;
     12 
     13 public class Notification implements PushModel {    
     14     private final Object alert;
     15     private final Set<PlatformNotification> notifications;
     16     
     17     private Notification(Object alert, Set<PlatformNotification> notifications) {
     18         this.alert = alert;
     19         this.notifications = notifications;
     20     }
     21     
     22     public static Builder newBuilder() {
     23         return new Builder();
     24     }
     25     
     26     /**
     27      * Quick set all platform alert. 
     28      * Platform notification can override this alert. 
     29      * 
     30      * @param alert Notification alert
     31      * @return first level notification object
     32      */
     33     public static Notification alert(Object alert) {
     34         return newBuilder().setAlert(alert).build();
     35     }
     36 
     37     public static Notification android(String alert, String title, Map<String, String> extras) {
     38         return newBuilder()
     39                 .addPlatformNotification(AndroidNotification.newBuilder()
     40                     .setAlert(alert)
     41                     .setTitle(title)
     42                     .addExtras(extras)
     43                     .build())
     44                 .build();
     45     }
     46 
     47     public static Notification ios(Object alert, Map<String, String> extras) {
     48         return newBuilder()
     49                 .addPlatformNotification(IosNotification.newBuilder()
     50                     .setAlert(alert)
     51                     .addExtras(extras)
     52                     .build())
     53                 .build();
     54     }
     55 
     56     public static Notification ios_auto_badge() {
     57         return newBuilder()
     58                 .addPlatformNotification(IosNotification.newBuilder()
     59                     .setAlert("")
     60                     .autoBadge()
     61                     .build())
     62                 .build();
     63     }
     64 
     65     public static Notification ios_set_badge(int badge) {
     66         return newBuilder()
     67                 .addPlatformNotification(IosNotification.newBuilder()
     68                     .setAlert("")
     69                     .setBadge(badge)
     70                     .build())
     71                 .build();
     72     }
     73 
     74     public static Notification ios_incr_badge(int badge) {
     75         return newBuilder()
     76                 .addPlatformNotification(IosNotification.newBuilder()
     77                     .setAlert("")
     78                     .incrBadge(badge)
     79                     .build())
     80                 .build();
     81     }
     82 
     83     public static Notification winphone(String alert, Map<String, String> extras) {
     84         return newBuilder()
     85                 .addPlatformNotification(WinphoneNotification.newBuilder()
     86                     .setAlert(alert)
     87                     .addExtras(extras)
     88                     .build())
     89                 .build();
     90     }
     91     
     92     public JsonElement toJSON() {
     93         JsonObject json = new JsonObject();
     94         if (null != alert) {
     95             if(alert instanceof JsonObject) {
     96                 json.add(PlatformNotification.ALERT, (JsonObject) alert);
     97             } else if (alert instanceof IosAlert) {
     98                 json.add(PlatformNotification.ALERT, ((IosAlert) alert).toJSON());
     99             } else {
    100                 json.add(PlatformNotification.ALERT, new JsonPrimitive(alert.toString()));
    101             }
    102         }
    103         if (null != notifications) {
    104             for (PlatformNotification pn : notifications) {
    105                 if (this.alert != null && pn.getAlert() == null) {
    106                     pn.setAlert(this.alert);
    107                 }
    108                 
    109                 Preconditions.checkArgument(! (null == pn.getAlert()), 
    110                         "For any platform notification, alert field is needed. It can be empty string.");
    111 
    112                 json.add(pn.getPlatform(), pn.toJSON());
    113             }
    114         }
    115         return json;
    116     }
    117     
    118     public static class Builder {
    119         private Object alert;
    120         private Set<PlatformNotification> builder;
    121         
    122         public Builder setAlert(Object alert) {
    123             this.alert = alert;
    124             return this;
    125         }
    126         
    127         public Builder addPlatformNotification(PlatformNotification notification) {
    128             if (null == builder) {
    129                 builder = new HashSet<PlatformNotification>();
    130             }
    131             builder.add(notification);
    132             return this;
    133         }
    134         
    135         public Notification build() {
    136             Preconditions.checkArgument(! (null == builder && null == alert), 
    137                     "No notification payload is set.");
    138             return new Notification(alert, builder);
    139         }
    140     }
    141 }

    当时使用时,感觉这种设计在使用时挺方便的,尤其是对参数的注入,可能构造一个Natification类所使用的代码有点长,但是对参数的使用十分明了。后来才知道这是Builder设计模式,当构造器需多个参数时,可显著改善可读性。根据此代码,自己也仿照写了相应的代码实现。

     1 package com.startup.code.designmode.builder;
     2 
     3 public class Person {
     4     
     5     private Name name;
     6     
     7     private Address address;
     8     
     9     private Person(Builder builder) {
    10         this.name = builder.name;
    11         this.address = builder.address;
    12     }
    13     
    14     @Override
    15     public String toString() {
    16         return this.name + "--" + this.address;
    17     }
    18     
    19     static class Builder{
    20         
    21         private Name name;
    22         
    23         private Address address;
    24         
    25         public Builder name(Name name) {
    26             this.name = name;
    27             return this;
    28         }
    29         
    30         public Builder address(Address address) {
    31             this.address = address;
    32             return this;
    33         }
    34         
    35         public Person build() {
    36             return new Person(this);
    37         }
    38     }
    39 }
    person类
     1 package com.startup.code.designmode.builder;
     2 
     3 public class Name {
     4     
     5     private String firstName; //
     6     private String lastName; //
     7     private String nickName; // 昵称
     8     private String usedName; // 曾用名
     9 
    10     @Override
    11     public String toString() {
    12         return "firstName:" + this.firstName + ",lastName:" + this.lastName + ",nickName:" + this.nickName + ",userdName:" + this.usedName;
    13     }
    14     
    15     private Name(Builder builder) {
    16         this.firstName = builder.firstName;
    17         this.lastName = builder.lastName;
    18         this.nickName = builder.nickName;
    19         this.usedName = builder.usedName;
    20     }
    21     
    22     /**
    23      * Name的内部构造类
    24      * @author chenq
    25      *
    26      */
    27     static class Builder {
    28         private String firstName;
    29         private String lastName;
    30         private String nickName;
    31         private String usedName;
    32         
    33         public Builder firstName(String firstName) {
    34             this.firstName = firstName;
    35             return this;
    36         }
    37         
    38         public Builder lastName(String lastName) {
    39             this.lastName = lastName;
    40             return this;
    41         }
    42         
    43         public Builder nickName(String nickName) {
    44             this.nickName = nickName;
    45             return this;
    46         }
    47         
    48         public Builder usedName(String usedName) {
    49             this.usedName = usedName;
    50             return this;
    51         }
    52         
    53         public Name build() {
    54             return new Name(this);
    55         }
    56     }
    57 }
    Name类
     1 package com.startup.code.designmode.builder;
     2 
     3 public class Address {
     4     
     5     private String province; //
     6     private String city; //
     7     private String district; // 区县
     8     
     9     private Address(Builder builder) {
    10         this.province = builder.province;
    11         this.city = builder.city;
    12         this.district = builder.district;
    13     }
    14     
    15     @Override
    16     public String toString() {
    17         return "province:" + this.province + ",city:" + this.city + ",district:" + this.district;
    18     }
    19     
    20     /**
    21      * Address的内部构造类
    22      * @author chenq
    23      *
    24      */
    25     static class Builder {
    26         private String province;
    27         private String city;
    28         private String district;
    29         
    30         public Builder province(String province) {
    31             this.province = province;
    32             return this;
    33         }
    34         
    35         public Builder city(String city) {
    36             this.city = city;
    37             return this;
    38         }
    39         
    40         public Builder district(String district) {
    41             this.district = district;
    42             return this;
    43         }
    44         
    45         public Address build() {
    46             return new Address(this);
    47         }
    48     }
    49 }
    Address

     测试类

    package com.startup.code.designmode.builder;
    
    public class BuilderTest {
        
        public static void main(String[] args) {
            Person person = new Person.Builder()
                            .address(new Address.Builder().province("江苏省").city("盐城市").district("建湖县").build())
                            .name(new Name.Builder().firstName("陈").lastName("群").nickName("rocky").usedName("陈大群").build())
                            .build();
            System.out.println(person);
        }
        
    }

    输出:

  • 相关阅读:
    day03 字符串
    day02 运算符和编码
    day01 初识Python
    windows 安装yaml支持和pytest支持等
    Python自动补全缩写意义
    关于python接口测试connect error
    关于Python的post请求报504错误
    python函数参数*args **kwargs
    利用Python语言Appium启动ios app
    shell 中| 用法
  • 原文地址:https://www.cnblogs.com/blog-cq/p/builder.html
Copyright © 2020-2023  润新知