设计模式共分为三种类型:创建型、结构型、行为型
- 创建型:用于创建对象,为设计类实例化新对象提供指南
- 结构型:用于处理类或对象的组合,对类如何设计以形成更大的结构提供指南
- 行为型:用于描述类或对象的交互以及职责的分配,对类之间交互以及分配职责的方式提供指南
定义来自权威的软考
常见的设计模式有如下几种
创建型:构建者、单例、工厂
结构型:适配器、代理、外观
行为型:策略、观察者、责任链
正文
Builder构建者
-
场景
用于生成对象的类其内部结构过于复杂,为屏蔽类的复杂性,需要将类的构建和表示进行分离,用最少的参数生成对象 -
例子
OkHttpClient
产生实际对象的必需参数是从builder对象中取出的
即使什么参数也不传Builder也会生成默认参数,以支持对象的生成
Builder
每次添加参数时,记得返回Builder对象,用以链式的传递
这是OkHttpClient对象传递参数的精妙之处,源码内多处使用
Singleton单例
- 场景
保证实例是唯一的存在,以保证操作的唯一性
单例模式的实现有两种:饱汉、饿汉模式
联想记忆:饱汉不饿,需要的时候再吃;饿汉很饥,提前抢着吃
饱汉其实是懒加载,不必提前占内存
- 例子
//饱汉模式
public class SingletonClass{
private static volatile SingletonClass instance=null;//静态变量保证对象的唯一性,volatile关键字防止指令重排
public static SingletonClass getInstance(){//使用内部加锁,避免每次调用时无谓的加锁,提升了性能
if(instance==null){//指令重排的话,其他线程看到instance不空,则不会进入,也不会加锁,直接返回半成品instance,从而导致异常
synchronized(SingletonClass.class){//锁对象最好是类对象(个人观点)
if(instance==null)//再判断一遍,避免多个线程在上一行同时被锁住,释放后进入,再次实例化对象
instance=new SingletonClass();//指令重排发生地
}
}
return instance;
}
private SingletonClass(){//私有构造方法,防止实例化
}
}
//饿汉模式
public static class Singleton{//静态类直接进入方法区常量池
private static final Singleton instance = new Singleton();//静态常量进入方法区常量池
private Singleton(){//私有构造方法,防止实例化
}
public static Singleton getInstance(){//静态方法
return instance;
}
}
饿汉模式,由于事先分配内存空间不存在饱汉的多线程问题,但其常驻内存会造成开销问题,不同的场景需采用不同的手段以保证消耗与效率的平衡。
Factory工厂
-
场景
多态场景下,用以管理生成不同的对象,并且耦合度不能够过高 -
例子
简单工厂模式
public interface Phone {//Phone是产品抽象
}
public class Honor implements Phone{//Honor是具体的产品
}
public class Mate20 implements Phone{//Mate20是具体的产品
}
public class HuaWei {//具体的厂商
public static Phone create(String str){//厂商根据要求生产手机
if(str.equalsIgnoreCase("honor")){
return new Honor();
}
else if(str.equalsIgnoreCase("mate20")){
return new Mate20();
}
return null;
}
}
工厂方法模式
public interface Phone {//Phone是产品抽象
}
public interface Factory {//Factory是厂商抽象
public Phone create();
}
public class HWPhone implements Phone{//华为手机
}
public class MPhone implements Phone{//小米手机
}
public class HuaWei implements Factory {//华为产华为手机
public Phone create(){
return new HWPhone();
}
}
public class XiaoMi implements Factory {//小米产小米手机
public Phone create(){
return new MPhone();
}
}
简单工厂模式:一个工厂类,工厂生产各种产品
工厂方法模式:一个工厂接口,多个工厂类,不同工厂生产不同产品
工厂方法模式的改进在于,减轻了简单工厂模式中工厂类的复杂度,具体的产出交由具体的工厂类,降低了耦合度。
抽象工厂模式
public interface Phone {//Phone是产品抽象
}
public interface OS {//OS是产品抽象
}
public interface Factory {//Factory是厂商抽象
public Phone create();
public OS develop();
}
public class HWPhone implements Phone{//华为手机
}
public class MPhone implements Phone{//小米手机
}
public class MIUI implements OS{//系统
}
public class EMUI implements OS{//系统
}
public class HuaWei implements Factory{//华为产华为手机
public Phone create(){
return new HWPhone();
}
public OS develop(){
return new EMUI();
}
}
public class XiaoMi implements Factory{//小米产小米手机
public Phone create(){
return new MPhone();
}
public OS develop(){
return new MIUI();
}
}
抽象工厂模式较工厂方法模式的区别在于,不生产单一产品,使工厂能够生产不同类型的相关产品,从而提高扩展性
在Retrofit中
使用的是工厂方法模式,将工厂抽象
初始化阶段,将实例化的不同工厂放在List中,根据参数使用情景的不同,再在List中取出合适的工厂进行处理。
Adapter适配器
-
场景
已有类的功能不满足需求,需将功能进行转换,以达到匹配 -
例子
类适配器模式
原有类并不具备某功能,通过创建Adapter类,继承原有功能、实现目标功能接口,从满足功能要求
public class Source {//现有类
public void method1() {
System.out.println("this is original method!");
}
}
public interface Targetable {//目标功能
public void method1();
public void method2();//缺失功能
}
public class Adapter extends Source implements Targetable {
@Override
public void method2() {//补足缺失
System.out.println("this is the targetable method!");
}
}
对象适配器模式
不同于类适配器模式,通过继承、实现这种高耦合手段,以满足功能要求。对象适配器模式采用的是聚合的手段,创建新类Wrapper通过持有原类对象具备原有功能外;并且类Wrapper实现功能接口补足缺失功能
如OkHttpClient中的Cache类
在OkHttpClient中缓存拦截器一层使用的是InternalCache,见注释,官方已经不建议使用此类改用Cache
Cache类本身并没有实现InternalCache接口,而是持有一个InternalCache对象,且对象内的方法都是调用Cache内的
接口适配器模式
不同于类适配器模式、对象适配器模式的补足功能,接口适配器模式恰恰相反:不暴露功能。
当接口