最近在看jdk源碼,想在畢業前再好好提高一下寫代碼的能力,jdk是個優秀的源碼閱讀範本(spring的源碼也不錯)。jdk目錄下的src.zip裡可以直接獲得源碼,我也push到了我github的一個repo裡。
網上搜了jdk設計模式,coolshell裡也有一篇,不過我還是參照了stackoverflow(原文連結)上的一個“examples of gof design
patterns”的答複,詳細列舉了jdk裡具體對應的類和函數,并結合了wiki上的許多整理好的優秀詞條内容。放到這個部落格上,也友善自己深入學習,好好體會下設計模式内涵,光看書也會很枯燥,況且紙質的代碼看起來也不舒服。
you can find an overview of a lot of design patterns in wikipedia.
it also mentions which patterns are mentioned by gof. i'll sum them up here and try to assign as much as possible pattern implementations found in both the java se and java ee api's.
<code>javax.xml.parsers.documentbuilderfactory#newinstance()</code>
<code>javax.xml.transform.transformerfactory#newinstance()</code>
<code>javax.xml.xpath.xpathfactory#newinstance()</code>
<code>java.lang.stringbuilder#append()</code> (unsynchronized)
<code>java.lang.stringbuffer#append()</code> (synchronized)
<code>java.nio.bytebuffer#put()</code> (also
on <code>charbuffer</code>, <code>shortbuffer</code>, <code>intbuffer</code>, <code>longbuffer</code>,<code>floatbuffer</code> and <code>doublebuffer</code>)
<code>javax.swing.grouplayout.group#addcomponent()</code>
all implementations of <code>java.lang.appendable</code>
<code>java.util.calendar#getinstance()</code>
<code>java.util.resourcebundle#getbundle()</code>
<code>java.text.numberformat#getinstance()</code>
<code>java.nio.charset.charset#forname()</code>
<code>java.net.urlstreamhandlerfactory#createurlstreamhandler(string)</code> (returns
singleton object per protocol)
<code>java.lang.object#clone()</code> (the
class has to implement <code>java.lang.cloneable</code>)
<code>java.lang.runtime#getruntime()</code>
<code>java.awt.desktop#getdesktop()</code>
<code>java.util.arrays#aslist()</code>
<code>java.io.inputstreamreader(inputstream)</code> (returns
a <code>reader</code>)
<code>java.io.outputstreamwriter(outputstream)</code> (returns
a <code>writer</code>)
<code>javax.xml.bind.annotation.adapters.xmladapter#marshal()</code> and <code>#unmarshal()</code>
none comes to mind yet. a fictive example would be <code>new linkedhashmap(linkedhashset<k>, list<v>)</code> which returns an unmodifiable linked map which doesn't clone the items, but uses them. the <code>java.util.collections#newsetfrommap()</code> and <code>singletonxxx()</code> methods
however comes close.
<code>java.awt.container#add(component)</code> (practically
all over swing thus)
<code>javax.faces.component.uicomponent#getchildren()</code> (practically
all over jsf ui thus)
all subclasses of <code>java.io.inputstream</code>, <code>outputstream</code>, <code>reader</code> and <code>writer</code> have
a constructor taking an instance of same type.
<code>java.util.collections</code>,
the <code>checkedxxx()</code>, <code>synchronizedxxx()</code> and <code>unmodifiablexxx()</code>methods.
<code>javax.servlet.http.httpservletrequestwrapper</code> and <code>httpservletresponsewrapper</code>
<code>javax.faces.context.facescontext</code>,
it internally uses among others the abstract/interface types <code>lifecycle</code>, <code>viewhandler</code>, <code>navigationhandler</code> and
many more without that the enduser has to worry about it (which are however overrideable by injection).
<code>javax.faces.context.externalcontext</code>,
which internally uses <code>servletcontext</code>,<code>httpsession</code>, <code>httpservletrequest</code>, <code>httpservletresponse</code>,
etc.
<code>java.lang.integer#valueof(int)</code> (also
on <code>boolean</code>, <code>byte</code>, <code>character</code>, <code>short</code> and <code>long</code>)
<code>java.lang.reflect.proxy</code>
<code>java.rmi.*</code>,
the whole api actually.
the
wikipedia example is imho a bit poor, lazy loading has actually completely nothing to do with the proxy pattern at all.
<code>java.util.logging.logger#log()</code>
<code>javax.servlet.filter#dofilter()</code>
all implementations of <code>java.lang.runnable</code>
all implementations of <code>javax.swing.action</code>
<code>java.util.pattern</code>
<code>java.text.normalizer</code>
all subclasses of <code>java.text.format</code>
all subclasses of <code>javax.el.elresolver</code>
all implementations of <code>java.util.iterator</code> (thus
among others also <code>java.util.scanner</code>!).
all implementations of <code>java.util.enumeration</code>
<code>java.util.timer</code> (all <code>schedulexxx()</code> methods)
<code>java.util.concurrent.executor#execute()</code>
<code>java.util.concurrent.executorservice</code> (the <code>invokexxx()</code> and <code>submit()</code> methods)
<code>java.util.concurrent.scheduledexecutorservice</code> (all <code>schedulexxx()</code> methods)
<code>java.lang.reflect.method#invoke()</code>
<code>java.util.date</code> (the
setter methods do that, <code>date</code> is
internally represented by a <code>long</code> value)
all implementations of <code>java.io.serializable</code>
all implementations of <code>javax.faces.component.stateholder</code>
<code>java.util.observer</code>/<code>java.util.observable</code> (rarely
used in real world though)
all implementations of <code>java.util.eventlistener</code> (practically
<code>javax.servlet.http.httpsessionbindinglistener</code>
<code>javax.servlet.http.httpsessionattributelistener</code>
<code>javax.faces.event.phaselistener</code>
<code>javax.faces.lifecycle.lifecycle#execute()</code> (controlled
by <code>facesservlet</code>,
the behaviour is dependent on current phase (state) of jsf lifecycle)
<code>java.util.comparator#compare()</code>,
executed by among others <code>collections#sort()</code>.
<code>javax.servlet.http.httpservlet</code>,
the <code>service()</code> and
all <code>doxxx()</code> methods
take<code>httpservletrequest</code> and <code>httpservletresponse</code> and
the implementor has to process them (and not to get hold of them as instance variables!).
all non-abstract methods of <code>java.io.inputstream</code>, <code>java.io.outputstream</code>, <code>java.io.reader</code>and <code>java.io.writer</code>.
all non-abstract methods of <code>java.util.abstractlist</code>, <code>java.util.abstractset</code> and<code>java.util.abstractmap</code>.
all the <code>doxxx()</code> methods
by default sends a http 405 "method not allowed" error to the response. you're free to implement none or any of them.
<code>javax.lang.model.element.annotationvalue</code> and <code>annotationvaluevisitor</code>
<code>javax.lang.model.element.element</code> and <code>elementvisitor</code>
<code>javax.lang.model.type.typemirror</code> and <code>typevisitor</code>
(全文完)