https://blog.csdn.net/angjunqiang/article/details/42061453
https://blog.csdn.net/baiye_xing/article/details/76427717
引入
我是從Stack Overflow上看到的問題,感覺這個答案真心不錯,所以翻譯過來看看,由於本文水平有限,不喜勿噴,原文鏈接:Examples of GoF Design Patterns in Java’s core libraries
問題
我正在學習GoF Java設計模式,我想看看他們的一些現實生活中的例子。Java核心庫中的這些設計模式的一些很好的例子是什么?
答案
我選擇了一個投票數最高(2515票)的答案來翻譯,同時我認為這也是最好的答案。
答案如下:
創作模式
抽象工廠模式 (通過創造性的方法來識別工廠本身,這又可以用於創建另一個抽象/接口類型)
- javax.xml.parsers.DocumentBuilderFactory#newInstance()
- javax.xml.transform.TransformerFactory#newInstance()
- javax.xml.xpath.XPathFactory#newInstance()
建造者模式 (通過創建方法識別返回實例本身)
- java.lang.StringBuilder#append() (非線程安全)
- java.lang.StringBuffer#append() (線程安全)
- java.nio.ByteBuffer#put()(還CharBuffer,ShortBuffer,IntBuffer,LongBuffer
- FloatBuffer和DoubleBuffer)
- javax.swing.GroupLayout.Group#addComponent()
- 所有的實現 java.lang.Appendable
工廠模式 (可通過創建方法識別返回抽象/接口類型的實現)
- java.util.Calendar#getInstance()
- java.util.ResourceBundle#getBundle()
- java.text.NumberFormat#getInstance()
- java.nio.charset.Charset#forName()
- java.net.URLStreamHandlerFactory#createURLStreamHandler(String) (每個協議返回單例對象)
- java.util.EnumSet#of()
- javax.xml.bind.JAXBContext#createMarshaller() 和其他類似的方法
原型模式 (通過創建方法識別,返回具有相同屬性的其他實例)
- java.lang.Object#clone()(班必須實施java.lang.Cloneable)
單例模式(通過創造性方法識別,每次返回相同的實例(通常是自己))
- java.lang.Runtime#getRuntime()
- java.awt.Desktop#getDesktop()
- java.lang.System#getSecurityManager()
結構模式
適配器模式 (可通過創建方法識別采用不同抽象/接口類型的實例,並返回自己/另一個抽象/接口類型的實現,其裝飾/覆蓋給定實例)
- java.util.Arrays#asList()
- java.util.Collections#list()
- java.util.Collections#enumeration()java.io.InputStreamReader(InputStream)(返回a Reader)
- java.io.OutputStreamWriter(OutputStream)(返回a Writer)
- javax.xml.bind.annotation.adapters.XmlAdapter#marshal() 和 #unmarshal()
橋接模式 (可以通過創建方法識別采用不同抽象/接口類型的實例,並返回自己的使用給定實例的抽象/接口類型的實現)
一個虛構的例子將會new LinkedHashMap(LinkedHashSet< K>, List< V>)返回一個不可修改的鏈接映射,它不會克隆,而是使用它們。該java.util.Collections#newSetFromMap()和singletonXXX()方法卻接近。
組合模式 (通過將具有相同抽象/接口類型的實例的行為方法識別為樹結構)
- java.awt.Container#add(Component) (幾乎全部擺動)
- javax.faces.component.UIComponent#getChildren()
裝飾器模式 (通過創作方法識別采用相同抽象/接口類型的實例,添加額外的行為)
- 所有子類java.io.InputStream,OutputStream,Reader並Writer有一個構造函數取相同類型的實例。
- java.util.Collections的checkedXXX(),synchronizedXXX()和unmodifiableXXX()方法。
- javax.servlet.http.HttpServletRequestWrapper 和 HttpServletResponseWrapper
門面模式 (可通過內部使用不同獨立抽象/接口類型實例的行為方法識別)
- javax.faces.context.FacesContext,它在內部等使用抽象/接口類型LifeCycle,ViewHandler,NavigationHandler等等而沒有終端用戶具有擔心它(它們然而通過注射覆寫投放)。
- javax.faces.context.ExternalContext,其在內部使用ServletContext,HttpSession,HttpServletRequest,HttpServletResponse,等。
享元模式 (使用緩存來加速大量小對象的訪問時間)
- java.lang.Integer#valueOf(int)(還Boolean,Byte,Character,Short,Long和BigDecimal)
代理模式 (可通過創建方法識別,該方法返回給定的抽象/接口類型的實現,該類型依次代表/使用給定抽象/接口類型的不同實現)
- java.lang.reflect.Proxy
- java.rmi.*
- javax.ejb.EJB
- javax.inject.Inject
- javax.persistence.PersistenceContext
行為模式
責任鏈模式 (通過行為方法識別(間接地)在隊列中的相同抽象/接口類型的另一個實現中調用相同的方法)
- java.util.logging.Logger#log()
- javax.servlet.Filter#doFilter()
命令模式 (可以通過抽象/接口類型中的行為方法識別,該方法在創建時由命令實現封裝的不同抽象/接口類型的實現中調用方法)
- 所有的實現 java.lang.Runnable
- 所有的實現 javax.swing.Action
解釋器模式 (通過行為方法識別,返回結構不同的實例/給定實例/類型的類型;請注意,解析/格式化不是模式的一部分,確定模式以及如何應用它)
- java.util.Pattern
- java.text.Normalizer
- 所有子類 java.text.Format
- 所有子類 javax.el.ELResolver
迭代器模式 (可通過行為方法識別,從隊列中順序返回不同類型的實例)
- 所有的實現java.util.Iterator(因此還有java.util.Scanner!)。
- 所有的實現 java.util.Enumeration
中介者模式 (通過采用不同的抽象/接口類型(通常使用命令模式)實例的行為方法來識別給定實例)
- java.util.Timer(所有scheduleXXX()方法)
- java.util.concurrent.Executor#execute()
- java.util.concurrent.ExecutorService(invokeXXX()和submit()方法)
- java.util.concurrent.ScheduledExecutorService(所有scheduleXXX()方法)
- java.lang.reflect.Method#invoke()
備忘錄模式 (可以通過內部改變整個實例的狀態的行為方法來識別)
- java.util.Date(setter方法這樣做,Date內部由一個long值表示)
- 所有的實現 java.io.Serializable
- 所有的實現 javax.faces.component.StateHolder
觀察者模式(或發布/訂閱) (可以通過行為方法識別,根據自己的狀態調用另一個抽象/接口類型的實例上的方法)
- java.util.Observer/ java.util.Observable(很少在現實世界中使用)
- 所有實現java.util.EventListener(因此實際上各地的Swing)
- javax.servlet.http.HttpSessionBindingListener
- javax.servlet.http.HttpSessionAttributeListener
- javax.faces.event.PhaseListener
狀態模式 (可以通過行為方法識別,根據可以從外部控制的實例的狀態改變其行為)
- javax.faces.lifecycle.LifeCycle#execute()(FacesServlet由此控制,行為取決於JSF生命周期的當前階段(狀態))
策略 (可以通過抽象/接口類型中的行為方法識別,該方法在已經作為方法參數傳遞到策略實現中的不同抽象/接口類型的實現中調用方法)
- java.util.Comparator#compare(),由其他人執行Collections#sort()。
- javax.servlet.http.HttpServlet,service()所有的doXXX()方法HttpServletRequest
- HttpServletResponse實現者必須處理它們(而不是把它們保持為實例變量!)。
- javax.servlet.Filter#doFilter()
模板方法 (可以由已經具有抽象類型定義的“默認”行為的行為方法識別)
- 所有非抽象方法java.io.InputStream,java.io.OutputStream,java.io.Reader和java.io.Writer。
- 所有非抽象方法java.util.AbstractList,java.util.AbstractSet和java.util.AbstractMap。
- javax.servlet.http.HttpServlet,doXXX()默認情況下,所有方法都會向響應發送HTTP 405“方法不允許”錯誤。你可以自由地執行任何一個或任何它們。
訪問者 (可以通過兩種不同的抽象/接口類型識別,它們的方法定義為采用每個其他抽象/接口類型;實際上調用另一個抽象/接口類型的方法,另一個執行所需的策略)
- javax.lang.model.element.AnnotationValue 和 AnnotationValueVisitor
- javax.lang.model.element.Element 和 ElementVisitor
- javax.lang.model.type.TypeMirror 和 TypeVisitor
- java.nio.file.FileVisitor 和 SimpleFileVisitor
熱門回復
1.Fuhrmanator
適配器示例太淺了。我希望看到一個適配器接口如何支持不同的適配接口,但是從示例中並不明顯。
2.Tapas Bose
@BalusC,我有一個問題要問你。你看了全部的 Java和JSF的源代碼?
3.dharam
當然這是一個很有名的答案,對於那些需要了解什么是工廠方法和抽象工廠方法的人,我認為有很多不符合GoF模式的模式1)工廠方法設計模式與靜態工廠無關,而且這個答案中的大多數例子都是靜態工廠。2)抽象工廠模式也與靜態工廠無關,這些只是編程習語。
4.Nishant Shreshth
在1.8中引入Calendar.Builder也是構建器模式的一個很好的例子。