设计模式梳理
一、概况
总体来说设计模式分为三大类:
(1)创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
(2)结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
(3)行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
二、设计模式的六大原则
1、开闭原则(Open Close Principle)
开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。
2、里氏代换原则(Liskov Substitution Principle)
(1)子类的能力必须大于等于父类,即父类可以使用的方法,子类都可以使用。
(2)返回值也是同样的道理。假设一个父类方法返回一个List,子类返回一个ArrayList,这当然可以。如果父类方法返回一个ArrayList,子类返回一个List,就说不通了。这里子类返回值的能力是比父类小的
(3)还有抛出异常的情况。任何子类方法可以声明抛出父类方法声明异常的子类而不能声明抛出父类没有声明的异常。
3、依赖倒转原则(Dependence Inversion Principle)
这个是开闭原则的基础,具体内容:面向接口编程,依赖于抽象而不依赖于具体。
4、接口隔离原则(Interface Segregation Principle)
这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。还是一个降低类之间的耦合度的意思,从这儿我们看出,其实设计模式就是一个软件的设计思想,从大型软件架构出发,为了升级和维护方便。所以上文中多次出现:降低依赖,降低耦合。
5、迪米特法则(最少知道原则)(Demeter Principle)
为什么叫最少知道原则,就是说:一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。
6、合成复用原则(Composite Reuse Principle)
原则是尽量使用合成/聚合的方式,而不是使用继承。
Java 常用十种设计模式示例归纳
Java - Examples of GoF Design Patterns
Java中使用了设计模式思想的类有哪些
Creational patterns--Abstract factory (recognizeable by creational methods returning the factory itself which in turn can be used to create another abstract/interface type)
Builder (recognizeable by creational methods returning the instance itself)
- javax.xml.parsers.DocumentBuilderFactory#newInstance()
- javax.xml.transform.TransformerFactory#newInstance()
- javax.xml.xpath.XPathFactory#newInstance()
Factory method (recognizeable by creational methods returning an implementation of an abstract/interface type)
- java.lang.StringBuilder#append() (unsynchronized)
- java.lang.StringBuffer#append() (synchronized)
- java.nio.ByteBuffer#put() (also on CharBuffer, ShortBuffer, IntBuffer, LongBuffer,FloatBuffer and DoubleBuffer)
- javax.swing.GroupLayout.Group#addComponent()
- All implementations of java.lang.Appendable
Prototype (recognizeable by creational methods returning a different instance of itself with the same properties)
- java.util.Calendar#getInstance()
- java.util.ResourceBundle#getBundle()
- java.text.NumberFormat#getInstance()
- java.nio.charset.Charset#forName()
- java.net.URLStreamHandlerFactory#createURLStreamHandler(String) (Returns singleton object per protocol)
Singleton (recognizeable by creational methods returning the same instance (usually of itself) everytime)
- java.lang.Object#clone() (the class has to implement java.lang.Cloneable)
Structural patterns--Adapter (recognizeable by creational methods taking an instance of different abstract/interface type and returning an implementation of own/another abstract/interface type which decorates/overrides the given instance)
Bridge (recognizeable by creational methods taking an instance of different abstract/interface type and returning an implementation of own abstract/interface type which delegates/uses the given instance)
- java.util.Arrays#asList()
- java.io.InputStreamReader(InputStream) (returns a Reader)
- java.io.OutputStreamWriter(OutputStream) (returns a Writer)
- javax.xml.bind.annotation.adapters.XmlAdapter#marshal() and #unmarshal()
Composite (recognizeable by behavioral methods taking an instance of same abstract/interface type into a tree structure)
- None comes to mind yet. A fictive example would be new LinkedHashMap(LinkedHashSet<K>, List<V>) which returns an unmodifiable linked map which doesn't clone the items, but uses them. The java.util.Collections#newSetFromMap() and singletonXXX() methods however comes close.
Decorator (recognizeable by creational methods taking an instance of same abstract/interface type which adds additional behaviour)
- java.awt.Container#add(Component) (practically all over Swing thus)
- javax.faces.component.UIComponent#getChildren() (practically all over JSF UI thus)
Facade (recognizeable by behavioral methods which internally uses instances of different independent abstract/interface types)
- All subclasses of java.io.InputStream, OutputStream, Reader and Writer have a constructor taking an instance of same type.
- java.util.Collections, the checkedXXX(), synchronizedXXX() and unmodifiableXXX()methods.
- javax.servlet.http.HttpServletRequestWrapper and HttpServletResponseWrapper
Flyweight (recognizeable by creational methods returning a cached instance, a bit the "multiton" idea) Proxy (recognizeable by creational methods which returns an implementation of given abstract/interface type which in turn delegates/uses a different implementation of given abstract/interface type)
- javax.faces.context.FacesContext, it internally uses among others the abstract/interface typesLifeCycle, ViewHandler, NavigationHandler and many more without that the enduser has to worry about it (which are however overrideable by injection).
- javax.faces.context.ExternalContext, which internally uses ServletContext, HttpSession, HttpServletRequest, HttpServletResponse, etc.
- java.lang.reflect.Proxy
- java.rmi.*, 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.
Behavioral patterns--Chain of responsibility (recognizeable by behavioral methods which (indirectly) invokes the same method inanother implementation of same abstract/interface type in a queue)
Command (recognizeable by behavioral methods in an abstract/interface type which invokes a method in an implementation of a different abstract/interface type which has been encapsulated by the command implementation during its creation)Interpreter (recognizeable by behavioral methods returning a structurally different instance/type of the given instance/type; note that parsing/formatting is not part of the pattern, determining the pattern and how to apply it is)
- All implementations of java.lang.Runnable
- All implementations of javax.swing.Action
Iterator (recognizeable by behavioral methods sequentially returning instances of a different type from a queue)
- java.util.Pattern
- java.text.Normalizer
- All subclasses of java.text.Format
- All subclasses of javax.el.ELResolver
Mediator (recognizeable by behavioral methods taking an instance of different abstract/interface type (usually using the command pattern) which delegates/uses the given instance)
- All implementations of java.util.Iterator (thus among others also java.util.Scanner!).
- All implementations of java.util.Enumeration
Memento (recognizeable by behavioral methods which internally changes the state of the whole instance)
- java.util.Timer (all scheduleXXX() methods)
- java.util.concurrent.Executor#execute()
- java.util.concurrent.ExecutorService (the invokeXXX() and submit() methods)
- java.util.concurrent.ScheduledExecutorService (all scheduleXXX() methods)
- java.lang.reflect.Method#invoke()
Observer (or Publish/Subscribe) (recognizeable by behavioral methods which invokes a method on an instance of another abstract/interface type, depending on own state)
- java.util.Date (the setter methods do that, Date is internally represented by a long value)
- All implementations of java.io.Serializable
- All implementations of javax.faces.component.StateHolder
State (recognizeable by behavioral methods which changes its behaviour depending on the instance's state which can be controlled externally)
- java.util.Observer/java.util.Observable (rarely used in real world though)
- All implementations of java.util.EventListener (practically all over Swing thus)
- javax.servlet.http.HttpSessionBindingListener
- javax.servlet.http.HttpSessionAttributeListener
- javax.faces.event.PhaseListener
Strategy (recognizeable by behavioral methods in an abstract/interface type which invokes a method in an implementation of a different abstract/interface type which has been passed-in as method argument into the strategy implementation)
- javax.faces.lifecycle.LifeCycle#execute() (controlled by FacesServlet, the behaviour is dependent on current phase (state) of JSF lifecycle)
Template method (recognizeable by behavioral methods which already have a "default" behaviour definied by an abstract type)
- java.util.Comparator#compare(), executed by among others Collections#sort().
- javax.servlet.http.HttpServlet, the service() and all doXXX() methods take HttpServletRequest and HttpServletResponse and the implementor has to process them (and not to get hold of them as instance variables!).
- javax.servlet.Filter#doFilter()
Visitor (recognizeable by two different abstract/interface types which has methods definied which takes each theother abstract/interface type; the one actually calls the method of the other and the other executes the desired strategy on it)
- All non-abstract methods of java.io.InputStream, java.io.OutputStream, java.io.Readerand java.io.Writer.
- All non-abstract methods of java.util.AbstractList, java.util.AbstractSet and java.util.AbstractMap.
- javax.servlet.http.HttpServlet, all the doXXX() methods by default sends a HTTP 405 "Method Not Allowed" error to the response. You're free to implement none or any of them.