[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 总结
- 导读
- Java知识
- Java基本程序设计结构
- 【基础知识】Java基础
- 【源码分析】Okio
- 【源码分析】深入理解i++和++i
- 【专题分析】JVM与GC
- 【面试清单】Java基本程序设计结构
- 对象与类
- 【基础知识】对象与类
- 【专题分析】Java类加载过程
- 【面试清单】对象与类
- 泛型
- 【基础知识】泛型
- 【面试清单】泛型
- 集合
- 【基础知识】集合
- 【源码分析】SparseArray
- 【面试清单】集合
- 多线程
- 【基础知识】多线程
- 【源码分析】ThreadPoolExecutor源码分析
- 【专题分析】volatile关键字
- 【面试清单】多线程
- Java新特性
- 【专题分析】Lambda表达式
- 【专题分析】注解
- 【面试清单】Java新特性
- Effective Java笔记
- Android知识
- Activity
- 【基础知识】Activity
- 【专题分析】运行时权限
- 【专题分析】使用Intent打开三方应用
- 【源码分析】Activity的工作过程
- 【面试清单】Activity
- 架构组件
- 【专题分析】MVC、MVP与MVVM
- 【专题分析】数据绑定
- 【面试清单】架构组件
- 界面
- 【专题分析】自定义View
- 【专题分析】ImageView的ScaleType属性
- 【专题分析】ConstraintLayout 使用
- 【专题分析】搞懂点九图
- 【专题分析】Adapter
- 【源码分析】LayoutInflater
- 【源码分析】ViewStub
- 【源码分析】View三大流程
- 【源码分析】触摸事件分发机制
- 【源码分析】按键事件分发机制
- 【源码分析】Android窗口机制
- 【面试清单】界面
- 动画和过渡
- 【基础知识】动画和过渡
- 【面试清单】动画和过渡
- 图片和图形
- 【专题分析】图片加载
- 【面试清单】图片和图形
- 后台任务
- 应用数据和文件
- 基于网络的内容
- 多线程与多进程
- 【基础知识】多线程与多进程
- 【源码分析】Handler
- 【源码分析】AsyncTask
- 【专题分析】Service
- 【源码分析】Parcelable
- 【专题分析】Binder
- 【源码分析】Messenger
- 【面试清单】多线程与多进程
- 应用优化
- 【专题分析】布局优化
- 【专题分析】绘制优化
- 【专题分析】内存优化
- 【专题分析】启动优化
- 【专题分析】电池优化
- 【专题分析】包大小优化
- 【面试清单】应用优化
- Android新特性
- 【专题分析】状态栏、ActionBar和导航栏
- 【专题分析】应用图标、通知栏适配
- 【专题分析】Android新版本重要变更
- 【专题分析】唯一标识符的最佳做法
- 开源库源码分析
- 【源码分析】BaseRecyclerViewAdapterHelper
- 【源码分析】ButterKnife
- 【源码分析】Dagger2
- 【源码分析】EventBus3(一)
- 【源码分析】EventBus3(二)
- 【源码分析】Glide
- 【源码分析】OkHttp
- 【源码分析】Retrofit
- 其他知识
- Flutter
- 原生开发与跨平台开发
- 整体归纳
- 状态及状态管理
- 零碎知识点
- 添加Flutter到现有应用
- Git知识
- Git命令
- .gitignore文件
- 设计模式
- 创建型模式
- 结构型模式
- 行为型模式
- RxJava
- 基础
- Linux知识
- 环境变量
- Linux命令
- ADB命令
- 算法
- 常见数据结构及实现
- 数组
- 排序算法
- 链表
- 二叉树
- 栈和队列
- 算法时间复杂度
- 常见算法思想
- 其他技术
- 正则表达式
- 编码格式
- HTTP与HTTPS
- 【面试清单】其他知识
- 开发归纳
- Android零碎问题
- 其他零碎问题
- 开发思路