2010-01-30 33 views
12

Joshua Bloch的Effective Java描述了一個Builder模式,可用於建立具有多個可選擇定製參數的對象。他爲Builder函數建議的命名約定「模擬Ada和Python中的命名可選參數」似乎不符合Java的標準命名約定。 Java函數往往依賴於有一個動詞來啓動函數,然後是一個基於名詞的短語來描述它的功能。 Builder類只具有由該函數定義的變量的名稱。Java API中生成器模式的示例?

Java標準庫中是否有使用Builder模式的API?我希望將本書中的建議與Java核心庫中的實際實現進行比較,然後再繼續使用。

+0

您可以在此SE問題找到例如:http://stackoverflow.com/questions/1673841/examples-of-gof-design-patterns-in-javas-core-libraries?rq = 1 – 2016-07-04 15:44:22

回答

17

我不知道有關核心JDK中,但很好的例子可以在Guava找到。 MapMaker可能是我能想到的最好的例子。例如,從文檔:

ConcurrentMap<Key, Graph> graphs = new MapMaker() 
    .concurrencyLevel(32) 
    .softKeys() 
    .weakValues() 
    .expiration(30, TimeUnit.MINUTES) 
    .makeComputingMap(
     new Function<Key, Graph>() { 
      public Graph apply(Key key) { 
      return createExpensiveGraph(key); 
      } 
     }); 

是的,這樣的事情可以違背「標準」 Java命名的糧食,但它也可以是非常具有可讀性。

對於不返回「this」而是返回新對象(通常使用不可變類型)的情況,我喜歡帶「前綴」前綴--Joda Time廣泛使用該模式。這不是建造者模式,而是一種替代和相關的建築形式。

0

它只在標準庫中定義(未實現),但JDBC DataSource對象使我想起構建器模式。您創建一個DataSource對象,然後設置一些屬性,然後建立連接。

下面是一個代碼示例...

DataSource ds = (DataSource)ctx.lookup("jdbc/AcmeDB"); 
ds.setServerName("my_database_server"); 
ds.setDescription("the data source for inventory and personnel"); 
Connection con = ds.getConnection("genius", "abracadabra"); 
0

ProcessBuilder是構建器模式的一個實例,但並未完全使用java命名約定。

 
ProcessBuilder pb = new ProcessBuilder("myCommand", "myArg1", "myArg2"); 
Map env = pb.environment(); 
env.put("VAR1", "myValue"); 
env.remove("OTHERVAR"); 
env.put("VAR2", env.get("VAR1") + "suffix"); 
pb.directory(new File("myDir")); 
Process p = pb.start(); 

在SQL包,PreparedStatement的可以考慮建造者模式的一個實例:

 
PreparedStatement stmt = conn.prepareStatement(getSql()); 
stmt.setString(1, ...); 
stmt.setString(2, ...); 
ResultSet rs = stmt.executeQuery(); 
... 
stmt.setString(2, ...); 
rs = stmt.executeQuery(); 
... 
+3

這不是一個完整的bui如果您不能鏈接方法,請使用模式。 – BalusC 2010-02-04 20:37:28

4

唯一的建設者最精確到有效的Java書的StringBuilder。 我從示例中看到的唯一區別是該構建器不是String的內部類。

所有方法都會將構建器對象返回鏈。而toString()方法是build()方法。

+0

'StringBuilder'不是構建器模式的實現,僅僅因爲它是構建器的名稱,它不會返回新的Object,而是相反。和平。 – 2017-11-17 16:39:48

0

SAXParser似乎是很好的例子:

  • SAXParser - 導演
  • ContentHandler - 構建

SAXParser的典型用法是生成器相同的:

// Create Director 
SAXParser parser = new org.apache.xerces.parsers.SAXParser(); 
// Create Concrete Builder (our own class) 
IdentingContentHandler handler = new IndentingContentHandler(); 
// Set Buidler to Director 
parser.setContentHandler(handler); 
// Build 
parser.parse(new InputSource(new FileReader(fileName)); 
// Get indented XML as String from handler 
String identedXML = handler.getResult(); 
0

相當好的例子是Calendar,例如,你可以使用:

Calendar cal = new Calendar.Builder().setCalendarType("iso8601") 
         .setWeekDate(2013, 1, MONDAY).build(); 

Java 7另一個很好的例子是Locale,使用:

Locale aLocale = new Builder().setLanguage("sr").setScript("Latn").setRegion("RS").build(); 

構建器模式在不可變對象的上下文中最爲有用。有趣的是,Java中有許多可變的構建器,StringBuilder是最常見的構建器。從Java 8易變的建設者:

  • Stream.Builder
  • IntStream.Builder
  • LongStream.Builder
  • DoubleStream.Builder