1、适配器
适配器是用来将一个类的接口转换为需要的另一个类。将原本不能一起工作的类一起工作。
源码案例 JDK1.8 中适配WSEndpoint 类的一个适配器。。可能是找源码太费劲了。
package com.sun.xml.internal.ws.transport.http.server;import com.sun.istack.internal.NotNull;import com.sun.xml.internal.ws.api.server.BoundEndpoint;import com.sun.xml.internal.ws.api.server.Module;import com.sun.xml.internal.ws.api.server.WSEndpoint;import com.sun.xml.internal.ws.api.server.WebModule;import com.sun.xml.internal.ws.transport.http.HttpAdapter;import com.sun.xml.internal.ws.transport.http.server.ServerAdapterList;import java.net.URI;import java.net.URISyntaxException;import java.util.logging.Level;import java.util.logging.Logger;import javax.xml.ws.WebServiceException;public final class ServerAdapter extends HttpAdapter implements BoundEndpoint { final String name; private static final Logger LOGGER = Logger.getLogger(ServerAdapter.class.getName()); protected ServerAdapter(String name, String urlPattern, WSEndpoint endpoint, ServerAdapterList owner) { super(endpoint, owner, urlPattern); this.name = name; Module module = (Module)endpoint.getContainer().getSPI(Module.class); if(module == null) { LOGGER.log(Level.WARNING, "Container {0} doesn\'\'t support {1}", new Object[]{endpoint.getContainer(), Module.class}); } else { module.getBoundEndpoints().add(this); } } public String getName() { return this.name; } @NotNull public URI getAddress() { WebModule webModule = (WebModule)this.endpoint.getContainer().getSPI(WebModule.class); if(webModule == null) { throw new WebServiceException("Container " + this.endpoint.getContainer() + " doesn\'t support " + WebModule.class); } else { return this.getAddress(webModule.getContextPath()); } } @NotNull public URI getAddress(String baseAddress) { String adrs = baseAddress + this.getValidPath(); try { return new URI(adrs); } catch (URISyntaxException var4) { throw new WebServiceException("Unable to compute address for " + this.endpoint, var4); } } public void dispose() { this.endpoint.dispose(); } public String getUrlPattern() { return this.urlPattern; } public String toString() { return super.toString() + "[name=" + this.name + ']'; }}
2、桥接
将抽象部分与实现部分分离,使他们可以独立变化。抽象与实现是持有关系。抽象持有实现。两者各自拓展。
类似与这种情况 JDBC数据库连接,DriverManager 是一个调用的接口,然后Driver实现DriverManager接口,数据库驱动再去实现 或 继承Driver 。
package com.sun.xml.internal.bind.v2.runtime
大量桥接代码。
3、组合(Composite)
组合模式适合单个对象组合成树形结构的情况。并且统一使用组合结构的所有对象。
用户使用Component接口与结构中的对象进行交互。通常如果接受者说一个叶子节点那么直接处理请求,如果说composite 那么他将转发给他的叶子节点,通常在转发的过程中还会有一些辅助操作。
component容易新增组件,left和composite可以使用同一个类(推荐),通过一个字段来判断,也可以写两个类分别实现,父组件应该支持责任链模式,这样可以方便操作。通过一个类实现和两个类实现就是在安全性和透明性之间作出选择。通过两个类实现要让Leaf 类和Composite类可以写一些缺省的实现。这样安全性会好,但是如果Leaf 类 要变成Composite要在Leaf和父Composite要有交互。通过一个类实现,具有良好的透明性,因为所有的类都是一样的,但是如果客户在Leaf中进行Composite操作这样就没有了安全性。
两个类。
package Design;/** * Created with IntelliJ IDEA. * Date: 17/11/4 * Time: 下午10:07 * * @author: Halo * @version: 1.0.0 * @Description: component */interface Component { Composite Get();}class Composite implements Component{ @Override public Composite Get() { return null; } void add(Component component){ //.... };}class Left implements Component{ @Override public Composite Get() { return null; } //...}class ComponentMain{ public static void main(String[] args) { Composite composite = new Composite(); Left left = new Left(); composite.add(left); }}
package Design;/** * Created with IntelliJ IDEA. * Date: 17/11/4 * Time: 下午10:07 * * @author: Halo * @version: 1.0.0 * @Description: component */interface Component { boolean isComponent(); Composite Get();}class Composite implements Component{ private boolean isComponent = false; @Override public boolean isComponent() { return this.isComponent; } public void setComponent(boolean component) { isComponent = component; } @Override public Composite Get() { return null; } void add(Component component){ if(isComponent()){ //... } return ; };}class ComponentMain{ public static void main(String[] args) { Composite composite = new Composite(); composite.setComponent(true); Composite left = new Composite(); composite.add(left); }}
如果要对组合进行频繁的遍历查找可以使用高速缓存存储相关信息。
4、装饰(Decorator)
装饰器希望动态的给一个对象添加一些额外的功能。
在不影响其他对象的情况下,用动态透明的方式给对象添加功能,并且这个对象不能采用生成子类的方式进行扩充。
装饰器比对象静态继承灵活,可以在运行时添加和删除功能,继承会为每个职责新增一个类,增加系统复杂度。
使用装饰器应该注意 装饰器的接口必须和所装饰的对象(Component)的接口一致,或拥有一个共同父类;只需要添加一个功能时,可以不用定义抽象类;保持Component的父类的简单性 因为装饰器和装饰对象共用一个父类接口,应该避免这个接口太过复杂;当Component十分复杂的时候,使用Decorator代价很高,可以采用Strategy模式。
Decorator模式不同与Adapter 的一点事Decorator 改变对象的功能但不改变他的接口,而Adapter给对象提供一个接口。
spring 中 的Decorator
public class WebSocketHandlerDecorator implements WebSocketHandler { private final WebSocketHandler delegate; public WebSocketHandlerDecorator(WebSocketHandler delegate) { Assert.notNull(delegate, "Delegate must not be null"); this.delegate = delegate; } public WebSocketHandler getDelegate() { return this.delegate; } public WebSocketHandler getLastHandler() { WebSocketHandler result; for(result = this.delegate; result instanceof WebSocketHandlerDecorator; result = ((WebSocketHandlerDecorator)result).getDelegate()) { ; } return result; } public static WebSocketHandler unwrap(WebSocketHandler handler) { return handler instanceof WebSocketHandlerDecorator?((WebSocketHandlerDecorator)handler).getLastHandler():handler; } //......}
public interface WebSocketHandler { void afterConnectionEstablished(WebSocketSession var1) throws Exception; void handleMessage(WebSocketSession var1, WebSocketMessage var2) throws Exception; void handleTransportError(WebSocketSession var1, Throwable var2) throws Exception; void afterConnectionClosed(WebSocketSession var1, CloseStatus var2) throws Exception; boolean supportsPartialMessages();}
具体的Component不给啦因为太多了随便一搜就有。
5、Facade 外观
一个系统划分为多个若干子系统,有利于降低系统复杂性,Facade为子系统提供一个对外的接口,使子系统和外界的通信和相互依赖关系达到最小。
当你要为一个复杂子系统提供一个简单接口时,你可以使用Facade ,Facade可以提供一个简单的缺省视图,这个视图对大多数客户已经够用,如果需要可定制,客户可以越过Facade 直接访问子系统。
Facade将子系统与外界分离,提高子系统的独立性和可移植性,松耦合。
Facade 将具体的请求路由到合适的子系统对象,子系统对象处理Facade对象指派的任务,但是没有指向Facade的指针。
Facade 一般只需要一个所以应该说单例的,
Facade可以与抽象工厂一起使用,
Facade和Mediator : Mediator 抽象了一些已有的类的功能。Mediator 的对象知道备忘录类与它通信,而不是直接与其他类对象通信,Facade仅仅对子系统的接口进行抽象,子系统不知道Facade的存在。
6、享元(Flyweight)
运用共享技术有效的支持大量细粒度对象。
'
flyweight是一个共享对象,可以在多个场景中使用,它的 内部状态存储于flyweight 中,包含了独立于flyweight场景的信息,这些信息使得flyweight可以被共享(比如围棋中的黑白子、编辑器中的单个字母)。而外部状态取决于flyweight场景,并根据场景变化,因此不可共享(比如棋子的位置,字母的所在的行和偏移位置)。用户对象负责在必要的时候将外部状态传递给Flyweight。
Flyweight适用于一个应用程序大量使用某一对象时,这些对象会造成很大的存储开销,对象的大多数状态都可变为外部状态。如果删除对象的外部状态,可以用相对较少的共享对象取代。
Flyweight经常和Composite结合使用。但是有一个缺点就是牺牲外部状态:Flyweight的叶节点不存储父节点的指针,父节点的指针将传递给Flyweight作为外部状态的一部分。
外部状态可以用一个单独的对象存储。Flyweight是共享的所以用户不能对他直接实例化,应该有一个Factory来创建,并且负责引用计数和gc。
7、代理(Proxy)
为其他对象提供一种代理以控制对这个对象的访问。
访问控制的原因是为了在需要这个对象的时候才对它进行创建和初始化。
Proxy和 Adapter 和 Decorator 类似。不同点在于Adapter 为对象生成一个适配的接口,Proxy 实现对象的接口、Decorator为对象添加一个或多个功能,Proxy为对象提供访问控制。