那天听到某大佬说面试被问到设计模式相关的问题,故特意重新将设计模式过了一遍,顺便稍微记录一下,以便以后复习可参考。
1、UML表示的相关规则
“可见性”表示该属性对类外的元素是否可见,包括公有(Public)、私有(Private)、受保护(Protected)和朋友(Friendly)4 种,在类图中分别用符号+、-、#、~表示
UML 中的类图有以下几种关系:依赖关系(带箭头虚线)、关联关系(带X个箭头的实线)、聚合关系(带空心菱形的实线)、组合关系(带实心菱形的实线)、泛化关系(带空心三角箭头的实线)和实现关系(带空心三角箭头的虚线)。其中泛化和实现的耦合度相等,它们是最强的。
2、面向对象设计原则
开闭原则:对扩展开放,对修改关闭
里氏替换原则:子类可以扩展父类的功能,但不能改变父类原有的功能
依赖倒置原则:通过要面向接口的编程来降低类间的耦合性
单一职责原则:对象(类)不应该承担太多职责
接口隔离原则:将臃肿庞大的接口拆分成更小的和更具体的接口
迪米特法则:只与你的直接朋友交谈,不跟“陌生人”说话
合成复用原则:尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现
3、设计模式分类
其中类模式采用的是继承机制,而对象模式采用的是组合或聚合,由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象模式比类模式具有更大的灵活性。
4、23种设计模式(含在Android中的应用)
创建型模式
单例模式:EventBus、数据库,分饿汉和懒汉
原型模式:Intent ,分浅克隆和深克隆
工厂方法模式:Retrofit的Converter.Factory、CallAdapter.Factory
抽象工厂模式:系列产品
建造者模式:Retrofit.Builder、OkHttpClient.Builder
结构型模式
代理模式:Binder通信原理、retrofit(动态代理)、 springAOP(动态代理)
目标类A与代理类B都实现了相同的接口C,代理类B持有目标类A的引用,在B中完成对A的调用,同时也可在调用前、后对功能进行增强或相应处理
适配器模式:接口转换,第三方扩展兼容统一
类适配器:类适配器A继承类适配者B,并实现目标接口C,在A中完成了将B的调用包装在C里
对象适配器:对象适配器A实现目标接口C,并持有类适配者B的引用,在A中完成了将B的调用包装在C里
桥接模式:多维扩展 聚合取代继承
抽象类 A里持有接口B的引用,A1、A2、A3...继承A,B1、B2、B3...实现B,完成了An与Bn的多种组合
装饰模式: Java I/O 标准库
具体构件类A实现抽象构件接口B,抽象装饰类C也实现抽象构件接口B,同时C持有B的引用,具体装饰类C1、C2、C3...继承C,Cn不仅能调用到A中的方法,还能附加自己的功能
外观模式:很多框架都有,门面,迪米特法则
外观类A持有子系统类A1、A2、A3...的引用,为A1、A2、A3...提供一个统一的对外接口(入口)
享元模式:String常量池,分单纯享元模式和复合享元模式
非享元类A以参数的方式传入到抽象享元接口B,具体享元类C实现抽象享元接口B,享元工厂类D负责管理和创建享元(可以用hashmap),完成了享元的共享和复用
组合模式:“部分-整体”的层次关系,树(枝、叶),分透明式和安全式
树叶构件类A和树枝构件类B都实现了抽象构件接口C,B主要是为了管理A,B中一般包含增删改查等方法,维护了A列表,因A、B都实现了C,所以调用方法起来,B会递归完成
行为型模式
模板方法模式:activity生命周期,AsyncTask,自己封装的基类等等
抽象类A定义了模板方法(抽象方法、具体方法、钩子方法),具体子类B实现A中的抽象方法和钩子方法,最终将按模板方法的顺序执行
策略模式:Recyclerview的LayoutManager,Volley的request
具体策略类A1、A2、A3...实现了抽象策略接口A,环境类B持有策略类的引用,达到了不同策略算法的选择,避免了多重条件判断
命令模式:handler消息机制,Volley发送request
具体命令类A1、A2、A3...实现了抽象命令接口A,An持有接收者类Bn,调用者类C持有A,故而C调用了A,An调用了Bn,完成了命令的下发,同时C和Bn解耦
责任链模式:android的事件分发机制,有序广播
具体处理类A实现了抽象处理类接口B,A中判断是否能进行处理,不能则传给后继者,由客户类C来创建并维护处理链,完成请求的链式下传,避免了多重条件判断
状态模式:线程的状态,只要你想登陆都可以使用状态模式
具体状态类A1、A2、A3...实现了抽象状态接口A,环境类B持有了A,B根据A的变化确定由An来执行,以此达到由状态改变行为,避免了多重条件判断
观察者模式:RxJava、EventBus、广播、点击事件都可以理解为观察者模式
具体观察者A1、A2、A3...实现了抽象观察者A,具体目标类B实现了抽象目标C中通知的方法,抽象目标C维护了一个A的集合(支持增删),当出现变化时,B会循环通知集合中的所有观察者A1、A2、A3...
中介者模式:MVP架构中的P,“网状结构”变为“星形结构”
具体同事类A1、A2、A3...实现了抽象同事类A中发送信息和接收信息的接口,抽象同事类A持有抽象中介者B的引用(用来实现A向B发送消息,请求中介转发),具体中介者C实现了抽象中介者B,并维护了一个A的集合(用来实现B向A发送消息,中介群发所有),由此建立了抽象同事类A和抽象中介者B的双向联系,完成了“一对多”转换为“一对一”
迭代器模式:Java中的 Collection、List、Set、Map 等都包含了迭代器,数据库Cursor游标
具体迭代器A实现了抽象迭代器B定义的hasNext()、first()、next() 等方法,A完成了对聚合列表的遍历,具体聚合类C实现了抽象聚合接口D定义的增删聚合对象及返回一个A对象,完成了聚合对象与其遍历行为的分离
访问者模式:多元素+多访问者+多行为(算法),关键是如何将作用于元素的操作分离出来封装成独立的类
对象结构类A维护了抽象元素B的集合,提供了增删元素方法,以及让某一访问者Cn遍历元素集合调用方法;
具体元素B1、B2、B3...实现抽象元素B,完成了由访问者调用元素的方法;
具体访问者C1、C2、C3...实现抽象访问者C,完成了元素操作方法的调用;
备忘录模式:activity的onSaveInstanceState和onRestoreInstanceState
备忘录A记录了发起人B中的状态信息,并提供给B使用,B中提供了创建A和恢复A的功能,管理者C提供了保存和获取A的功能
解释器模式:AndroidManifest.xml解释
终结符表达式A、非终结符表达式B都实现抽象表达式C,A、B各自解释判断自己对应的终结/非终结表达式,环境类D提供A、B需要的数据或公共功能
PS:说真的,看这些比写代码看代码还累,看得我直打盹,幸好坚持就是胜利啊!!!
参考链接:
http://c.biancheng.net/view/1317.html
https://www.jianshu.com/p/a3e844619ed2