🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] 结构型模式(Structural Pattern)描述如何将类或者对象结合在一起形成更大的结构,就像搭积木,可以通过简单积木的组合形成复杂的、功能更为强大的结构。 结构型模式可以分为类结构型模式和对象结构型模式。 参考文档: [代理模式及Java实现动态代理](http://www.jianshu.com/p/6f6bb2f0ece9) # 1 适配器模式 ## 1.1 模式定义 适配器模式(Adapter Pattern):将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。适配器模式既可以作为类结构型模式,也可以作为对象结构型模式。 ## 1.2 模式结构 * Target:目标抽象类 定义客户要用的特定领域的接口 * Adaptee:适配者类 是被适配的角色,它定义了一个已经存在的接口,这个接口需要适配 * Adapter:适配器类 可以调用另一个接口,作为一个转换器,对适配者和抽象目标类进行适配,它是适配器模式的核心 * Client:客户类 针对目标抽象类进行编程,调用在目标抽象类中定义的业务方法 ## 1.3 代码示例 ```java // 目标类 public interface LightningCharger { void chargeWithLightning(); } // 适配者类 public class MicroUSBCharger { public void chargeWithMicroUSB() { } } // 适配器类 public class ChargerAdapter implements LightningCharger { private MicroUSBCharger mMicroUSBCharger; public ChargerAdapter(MicroUSBCharger microUSBCharger) { mMicroUSBCharger = microUSBCharger; } @Override public void chargeWithLightning() { mMicroUSBCharger.chargeWithMicroUSB(); } } // 客户类 MicroUSBCharger microUSBCharger = new MicroUSBCharger(); LightningCharger lightningCharger = new ChargerAdapter(microUSBCharger); lightningCharger.chargeWithLightning(); ``` ## 1.4 总结 * 在类适配器模式中,适配器类实现了目标抽象类接口并继承了适配者类,并在目标抽象类的实现方法中调用所继承的适配者类的方法; * 在对象适配器模式中,适配器类继承了目标抽象类并定义了一个适配者类的对象实例,在所继承的目标抽象类方法中调用适配者类的相应业务方法。 * 适配器模式的主要优点是将目标类和适配者类解耦,增加了类的透明性和复用性,同时系统的灵活性和扩展性都非常好,更换适配器或者增加新的适配器都非常方便,符合“开闭原则”; * 类适配器模式的缺点是适配器类在很多编程语言中不能同时适配多个适配者类,对象适配器模式的缺点是很难置换适配者类的方法。 * 适配器模式适用情况包括:系统需要使用现有的类,而这些类的接口不符合系统的需要;想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类一起工作。 # 2 代理模式 ## 2.1 模式定义 给某个对象提供一个代理对象,并由代理对象控制对于原对象的访问,即客户不直接操控原对象,而是通过代理对象间接地操控原对象。 ## 2.2 模式结构 * Subject:抽象主题角色 声明了真实主题和代理主题的共同接口 * Proxy:代理主题角色 内部包含对真实主题的引用,从而可以在任何时候操作真实主题对象 * RealSubject:真实主题角色 定义了代理角色所代表的真实对象,在真实主题角色中实现了真实的业务操作,客户端可以通过代理主题角色间接调用真实主题角色中定义的方法 ## 2.3 代码示例 抽象主题角色: ```java public interface Subject { void request(); } ``` 真实主题角色: ```java public class RealSubject implements Subject { private static final String TAG = "RealSubject"; @Override public void request() { Log.e(TAG, "request: "); } } ``` 代理主题角色: ```java public class Proxy implements Subject { private static final String TAG = "Proxy"; private Subject mRealSubject; @Override public void request() { Log.e(TAG, "request: preRequest"); if (mRealSubject == null) { mRealSubject = new RealSubject(); } mRealSubject.request(); Log.e(TAG, "request: postRequest"); } } ``` 客户端类: ```java public class Client { public static void main(String[] args) { Subject subject = new Proxy(); subject.request(); } } ``` 代理模式又分为: * 静态代理:代理类在编译时就是实现好的 * 动态代理:代理类是在运行时生成的,也就是 Java 编译完成后并没有代理类的 class 文件,而是在运行时动态生成的类字节码 下面看看 Java 实现动态代理: 动态代理的结构除了上面的抽象主题、代理主题、真实主题外,还增加了一个: 调用处理器: 需要实现 InvocationHandler 接口,用来指定运行时将生成的代理类需要完成的任务。 同时,代理类 Proxy 需要继承 java.lang.reflect.Proxy。 抽象主题: ```java public interface Subject { void request(); } ``` 真实主题: ```java public class RealSubject implements Subject { private static final String TAG = "RealSubject"; @Override public void request() { Log.e(TAG, "request: "); } } ``` 调用处理器: ```java public class ProxyHandler implements InvocationHandler { private static final String TAG = "ProxyHandler"; private Subject mSubject; public ProxyHandler(Subject subject) { mSubject = subject; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Log.e(TAG, "invoke: before"); Object result = method.invoke(mSubject, args); Log.e(TAG, "invoke: after"); return result; } } ``` 客户端: ```java public class Client { public static void main(String[] args) { RealSubject realSubject = new RealSubject(); ProxyHandler handler = new ProxyHandler(realSubject); Subject proxySubject = (Subject) Proxy.newProxyInstance(RealSubject.class.getClassLoader(), RealSubject.class.getInterfaces(), handler); proxySubject.request(); } } ``` ## 2.4 总结 * 优点在于能够协调调用者和被调用者,在一定程度上降低了系统的耦合度 * 缺点在于由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢,并且实现代理模式需要额外的工作,有些代理模式的实现非常复杂 本段参考文档: [代理模式及Java实现动态代理](http://www.jianshu.com/p/6f6bb2f0ece9) [公共技术点之 Java 动态代理]([https://a.codekk.com/detail/Android/Caij/公共技术点之%20Java%20动态代理](https://a.codekk.com/detail/Android/Caij/%E5%85%AC%E5%85%B1%E6%8A%80%E6%9C%AF%E7%82%B9%E4%B9%8B%20Java%20%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86)) # 3 门面模式 又称外观模式。 ## 3.1 模式定义 门面模式是对象的结构模式,外部与一个子系统的通信必须通过一个统一的门面对象进行。门面模式提供一个高层次的接口,使得子系统更易于使用。 ## 3.2 模式结构 * 门面角色(Facade): 门面角色为子系统中的一组接口提供一个一致的界面,客户端可以调用这个角色的方法。此角色知晓相关的(一个或者多个)子系统的功能和责任。在正常情况下,本角色会将所有从客户端发来的请求委派到相应的子系统去 * 子系统角色(SubSystem): 可以同时有一个或者多个子系统。每个子系统都不是一个单独的类,而是一个类的集合。每个子系统都可以被客户端直接调用,或者被门面角色调用。子系统并不知道门面的存在,对于子系统而言,门面仅仅是另外一个客户端而已。 ## 3.3 代码示例 ## 3.4 总结