手裡拿著錘子,看啥都像釘子

hjavn發表於2021-08-17

工具與資源中心

幫助開發者更加高效的工作,提供圍繞開發者全生命週期的工具與資源
developer.aliyun.com/tool?spm=a1z3...

有人在我的構造器文章下提了下面一個問題:

老師,提一個問題,在實際生活中遇到的 比如說我寫了一個傳送訊息的方法。比如說有一個引數是 messageDTO,但是他有很多屬性,比如說 topic,tag,shadingKey,msg, delayTime 等等,但是我希望別人在使用這個方法的時候傳入 messageDTO 是我想要的,即我會將無參構造方法私有化,因為我不想讓別人使用無參構造new一個物件出來,(因為自己去set可能某一些引數設定有遺漏),然後只限制了 幾種建構函式,或者使用靜態方法來建立物件。
然後物件的入參是由要求的。比如說你想法 普通訊息,那麼需要 topic和msg,發延遲訊息,需要topic msg和delayTime,發順序訊息需要額外再加一個shadingKey,請問在這種情況下如何使用建造者模式。即只允許使用某一組引數來建立物件

每種設計模式(甚至任何技術)都有自己適合的場景。
雖然我們學了建造者模式,未必一定要用建造者模式。

針對這種場景,有很多方法可以更優雅地實現:

  • 可以使用工廠模式,通過函式名體現型別。
  • 可以通過繼承的方式通過類名來體現型別。
  • Builder 模式變通。

2.1 靜態工廠

MessageFactory類
構造普通訊息

public static MessageDTO buildCommonMsg(String topic, String msg) {

// 直接 new 然後 set 或者用 builder都可以
}

構造延時訊息

 public  static MessageDTO buildDelayMsg(String topic, String msg,Long delayTime) {
// 省略
 }

順序訊息類似

 public static MessageDTO buildOrderedMsg(String topic, String msg, String shadingKey) 
{
    // 省略
 }

可以加上引數校驗。

2.2 利用繼承來表意

普通訊息 CommonMsgDTO

public class CommonMsgDTO{
  private String topic;
  private String msg;

   // 提供全參構造方法
}

延時訊息 DelayMsg

public class DelayMsgDTO extends CommonMsgDTO{
  private Long delayTime;

   // 提供全參構造方法
}

順序訊息 DelayMsg

public class OrderedMsgDTO extends CommonMsgDTO{
  private String shadingKey;

   // 提供全參構造方法
}

這樣構造時只有全引數建構函式,就不容易傳錯,而且看名知意。
如果傳 null 可以報錯。


2.3 builder模式活用

public static class Builder{  
 // 省略
 public Builder(String topic, String msg){
   // 省略
 }
   // 其他屬性的set 方法
}  

對普通的 builder 模式稍微改造下,將必備引數作為 Builder 的唯一建構函式的引數。
這樣必備屬性必然會傳入。
但是如果必傳引數太多,不推薦使用這種方式。


哪怕是不同的 builder 模式,在 build時進行引數校驗。

可能還有很多解決方案,上面給出兩個比較簡單且常見的方法。
在執行傳送訊息的函式上加上引數校驗,這樣就不容易出錯。

希望大家一定要破除 ”手裡拿著錘子,看啥都像釘子“的心理。
在學習任何技術時,思考其最適合的場景,為了解決什麼問題,侷限是什麼。

在解決問題前想清楚問題是什麼?

比如這位同學核心是為了能讓使用者清晰地區分型別,然後讓使用者知道不同型別的引數差異。
然後再去思考怎樣更容易區分開呢?必傳引數一定要早構造的時候校驗嗎?
慢慢地,問題就明瞭了,就更容易得到更科學的答案。

總之,既要埋頭苦學,又要抬頭看路。學而不思則罔!

本文轉自:developer.aliyun.com/article/78724...

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章