概况来看本文章的内容
创建型:5 个
单例模式
Builder
原型模式
工厂方法
抽象工厂
行为型: 11 个
策略模式
状态模式
观察者模式
中介者模式
访问者模式
迭代器模式
模板方法
备忘录模式
命令模式
解释器模式
职责链模式
结构型:7 个
组合模式
代理模式
装饰模式
外观模式
享元模式
桥接模式
适配器模式
关于面向对象
面向对象的六大原则
谈到设计模式,不得不说说面向对象的六大原则
1. 单一原则
单一原则通俗的讲就是一个类只表达一个概念,一个方法只做一件事情.将一组相关性很高的函数,数据封装到一个类中.换句话说,一个类应该有职责单一.
2. 开闭原则
开闭原则就是一个类对于扩展是开发的,但是对于修改是封闭的.这也是六大原则中最难的,通常开闭都是短暂的美好,但在业务升级与拓展的状态下,原理的开闭是无法满足.即使是这样,也要尽可能的扩展而不是修改.
3. 里氏替换原则
所有引用基类的地方必须能透明地使用其子类对象.看着定义很是抽象,但是通俗的理解就是由子类实例化的父类引用,在使用这个引用时,感觉就像是使用了父类一样.一个简单的例子:
4. 依赖倒置原则
public class T{
private class A{...}
class B extends A{...}
public static void main(String[] args){
A a = new B();
// 类型是A,但实际是B类型实例化的
a.method();
}
}
依赖倒置主要是为了解耦.具体来说:
高层模块不应该依赖底层模块,二者都应该依赖其抽象
抽象不应该依赖细节
细节应该依赖抽象
5. 接口隔离原则
类之间的依赖关系应该建立在最小的接口上其原则是将繁杂的功能接口拆分成更加单一职责的接口,防止接口内部的耦合.
6. 迪米特原则
一个对象应该对其他的对象有最少的了解 保留关键的共有方法,其他次要的都是私有方法,不应该被外部了解.
Android 来表达面向对象的六大原则
1. 单例模式
定义:确保单例类只有一个实例,并且这个单例类提供一个函数接口让其他类获取到这个唯一的实例.
单例模式的意义是显而易见的,能极大的节省资源,提高代码运行效率.缺点也是很明确的,就是不能发生状态的变化,以提供统一的功能.
单例模式有懒汉式与饿汉式,实现方式有静态成员变量法,枚举法,容器法等.单例需要注意的就是懒汉模式下的多线程安全问题.这里给出懒汉模式比较优雅的实现代码,其原理就是类加载器 ClassLoader 保证了并发的安全性.
Android 系统下的单例模式有
public class Singleton {
private Singleton() {}
public static synchronized Singleton getInstance() {
return SingletonHolder.instance;
}
private static class SingletonHolder {
private static final Singleton instance = new Singleton();
}
}
2. Builder 模式
//获取WindowManager服务引用
WindowManager wm = (WindowManager) getSystemService(getApplication().WINDOW_SERVICE);
定义:将一个复杂对象的构造与它的表示分离,使得同样的构造过程可以创建不同的表示.
从上述代码中可以非常直观的看出 Builder 模式就是先设置好各种参数,然后再通过一个方法的调用构建出来一个复杂的对象.
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setIcon(R.drawable.icon)
.setTitle("title")
.setMessage("message")
.setPositiveButton("OK", null)
// create之前的set方法操作的都是AlertDialog.Builder而已
.create()
// create之后就创建出一个真实的AlertDialog了,将复杂的创建过程都隐藏在create方法内部
.show();
3. 原型模式
原型模式很简单,使用一个实例拷贝后的实例.
在 java 中拷贝存在深拷贝与浅拷贝,如果类中的成员变量都是基本数据类型,则系统自动实现这些基本数据类型的深拷贝.
那何时要用到原型模式呢?防止自己的实例在传入别的模块后,发生意外的修改.进行一次拷贝,再将该实例当做参数传递给别人,是非常明智的操作,尤其是这个实例是某个类的成员变量.
4. 工厂方法模式
Uri uri = Uri.parse("smsto:10086");
Intent shareIntent = new Intent(Intent.ACTION_SENDTO, uri);
// 这里举例说明intent是提供了一次clone方法的
Intent intent = shareIntent.clone();
// 假设startActivity方法会修改intent
startActivity(intent);
// 然后接着使用shareIntent进行其他操作
// 如果不clone,鬼知道shareIntent会变成什么样子
shareIntent.putExtra("key", "extra")
...
定义:定义一个创建对象的接口,让子类决定实例化哪个类
Android 下的例子有 BitmapFactory
public abstract class Product {
public abstract void method();
}
public abstract class Factory {
public abstract Product createProduct();
}
public class ConcreteProductA extends Prodect {
public void method() {
System.out.println("我是产品A!");
}
}
public class ConcreteProductB extends Prodect {
public void method() {
System.out.println("我是产品B!");
}
}
// 类的实例化被推迟到了子类
public class MyFactory extends Factory {
public Product createProduct() {
return new ConcreteProductA();
}
}
5. 抽象工厂模式
public class BitmapFactory {
public static Bitmap decodeFile(String pathName, Options opts) {
Bitmap bm = null;
......
return bm;
}
}
定义:为创建一组相关或者是相互依赖的对象提供一个接口,而不需要制定他们的具体类
抽象工厂与工厂方法的区别,表面上看就是生产线是多条,还是有一条.但其设计模式的思想是表达了抽象工厂表示一组关联的生产线,而不仅仅是表示同一类型的生产线.
public abstract class AbstractProductA{
public abstract void method();
}
public abstract class AbstractProdectB{
public abstract void method();
}
// 这个工厂一旦创建,就天生必须拥有两条生产线,具体生产什么,将由子类决定
public abstract class AbstractFactory{
public abstract AbstractProductA createProductA();
public abstract AbstractProductB createProductB();
}
public class ConcreteProductA1 extends AbstractProductA{
public void method(){System.out.println("具体产品A1的方法!");}
}
public class ConcreteProductA2 extends AbstractProductA{
public void method(){System.out.println("具体产品A2的方法!");}
}
public class ConcreteProductB1 extends AbstractProductB{
public void method(){System.out.println("具体产品B1的方法!");}
}
public class ConcreteProductB2 extends AbstractProductB{
public void method(){System.out.println("具体产品B2的方法!");}
}
public class ConcreteFactory1 extends AbstractFactory{
public AbstractProductA createProductA(){return new ConcreteProductA1();}
public AbstractProductB createProductB(){return new ConcreteProductB1();}
}
public class ConcreteFactory2 extends AbstractFactory{
public AbstractProductA createProductA(){return new ConcreteProductA2();}
public AbstractProductB createProductB(){return new ConcreteProductB2();}
}
0.0 简单工厂
这并不是一个真正的模式,但是和抽象工厂和工厂方法模式一样,它经常被用于封装创建对象的代码
6. 策略模式
// 根据传入的参数决定给出哪个Service
public Object getSystemService(String name) {
if (getBaseContext() == null) {
throw new IllegalStateException("System services not available to Activities before onCreate()");
}
//........
if (WINDOW_SERVICE.equals(name)) {
return mWindowManager;
} else if (SEARCH_SERVICE.equals(name)) {
ensureSearchManager();
return mSearchManager;
}
//.......
return super.getSystemService(name);
}
定义:有一系列的算法,将每个算法封装起来(每个算法可以封装到不同的类中),各个算法之间可以替换,策略模式让算法独立于使用它的客户而独立变化.
Android 的属性动画中使用时间插值器,就是策略模式.
public abstract class AbstractSortAlgorithm {
public abstract sort(List list);
}
public class CustomList extends List {
private AbstractSortAlgorithm algorithm;
public void setSortAlgorithm(AbstractSortAlgorithm algorithm){this.algorithm = algorithm;}
public void sortList() {algorithm.sort(this);}
}
7. 状态模式
允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类.
状态模式在 Android 下使用的还是很多的,比如 WIFI 在开启时,自动扫描周围的接入点,然后以列表展示,当 WIFI 关闭时,清空列表.
public abstract class Actor {
public abstract void act();
}
class GirlActor extends Actor{
public void act(){System.out.println("GirlActor");}
}
class BoyActor extends Actor{
public void act(){System.out.println("BoyActor");}
}
class Stage{
private Actor actor;
public void firstFrame(Actor actor){this.actor = new GirlActor();}
public void secondFrame(Actor actor){this.actor = new BoyActor();}
// 在不同的状态下会有不同的输出
public void performPlay(){
actor.act();
}
}
8. 责任链模式
定义:使多个对象都有机会处理请求,从而避免请求的发送者和接收者直接的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止.
最好的一个例子就是 View 的测量,定位,绘制,事件传递,事件分发等.这些例子都是从父 View 开始依次向子 View 进行,是一个特别典型的责任链模式.特别要提到的是,savedInstance 的处理也是责任链模式.
9. 解释器模式
定义:给定一个语言,定义它的语法,并定义个解释器,这个解释器用于解析语言.
通俗的来讲,就是自定义一个格式文件,然后解析它.
AndroidManifest.xml 是典型的一个自定义 xml 文件语言,layout 目录下的 xml 文件,都是具有特殊语法的文件.他们都会被 XmlPullParser 这个解析器进行解释.
10. 命令模式
定义:命令模式将每个请求封装成一个对象,从而让用户使用不同的请求把客户端参数化;将请求进行排队或者记录请求日志,以及支持可撤销操作.
在 Android 底层的事件机制中,底层逻辑对事件的转发处理.每次的按键事件会被封装成 NotifyKeyArgs 对象,通过 InputDispatcher 封装具体的事件操作.
11. 观察者模式
定义:定义了对象之间的一对多的关系,其实就是 1:n,当 "1" 发生变化时,"n" 全部得到通知,并更新.
观察者模式比较典型的场景就是发布消息通知订阅者.没错 Android 下的广播就是观察者模式,在 FrameWork 层,状态发生变化后(比如 WIFI 状态),会遍历全部的 register.
12. 备忘录模式
定义:在不破坏封闭的前提下,捕获一个对象的内部状态,并在对象之外保存这个状态,这样,以后就可以将对象恢复到原先保存的状态中.
通俗的讲就是一个提前备份,一旦出现问题,能尽可能的恢复到最接近之前的状态.
Android 下的 onSaveInstanceState 就在时不时的进行着备忘,在 onRestoreInstanceState 时,就能取出最后的记录.
13. 迭代器模式
定义:提供一种方法顺序访问一个容器对象中的各个元素,而不需要暴露该对象的内部表示.
这个迭代器再好理解不过了,我们天天用的 Iterator 正是这种迭代器模式.
在 Android 中 SQLiteDatabase 的 query 也是迭代器模式
14. 模板方法模式
cursor = database.query(...);
while (cursor.moveToNext()) {
cursor.get...;
}
定义:定义一个操作中的算法框架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重定义该算法的某些特定的步骤.
直接看代码
可以看出模板方法就是留出适当的方法等待子类来实现.不管如何重写父类,父类的主逻辑将不会被改变.
public class CustomActivity extends Activity {
// Activity留给用户自定义某些特定步骤
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// ... ...
}
}
15. 访问者模式
定义:封装一些作用于某些数据结构中各元素的操作,它可以在不改变这个数据的前提下定义作用于这些元素的新的操作.
Android 中很少使用访问者模式,ButterKnife 中到是使用了.
这里只给出一个案例:
场景:一群人到你家,一起喂食宠物
抽象宠物角色(被访问者):动物抽象类
抽象访问者角色(访问者):给宠物喂食的人
具体被访问者:狗,猫
结构对象角色:主人家
具体访问者:主人,其他人
下面就具体来看实现:
创建抽象节点 -- 宠物
创建抽象访问者接口
interface Animal {
void accept(Person person);
}
创建 Animal 接口的具体节点
interface Person {
void feed(Cat cat);
void feed(Dog dog);
}
创建具体访问者角色
class Dog implements Animal {
@Override public void accept(Person person){
person.feed(this);
System.out.println("旺旺");
}
}
class Cat implements Animal {
@Override public void accept(Person person){
person.feed(this);
System.out.println("喵喵");
}
}
具体的结构对象,访问者与被访问者的交互空间,准确地说是 Person 访问 Animal
class Owner implements Person {
@Override public void feed(Cat cat) {System.out.println("主人喂食猫");}
@Override public void feed(Dog dog) {System.out.println("主人喂食狗");}
}
class Someone implements Person {
@Override public void feed(Cat cat) {System.out.println("客人喂食猫");}
@Override public void feed(Dog dog) {System.out.println("客人喂食狗");}
}
最后进行测试
class Home {
private List<Animal> nodeList = new ArrayList<>();
void add(Animal animal) {nodeList.add(animal);}
void action(Person person) {
for (Animal node : nodeList) {node.accept(person);}
}
}
16. 中介者模式
public class Test {
public static void main(String[] args) {
Home home = new Home();
home.add(new Dog());
home.add(new Cat());
Owner owner = new Owner();
home.action(owner);
Someone someone = new Someone();
home.action(someone);
}
}
定义:中介者模式包装了一系列对象相互作用的方式,使得这些对象不
必相互明显调用,从而使他们可以轻松解耦.当某些对象之间的作用发生改变时,不会立即影响其他的一些对象之间的作用,保证这些作用可以彼此独立的变化,中介者模式将多对多的相互作用转为一对多的相互作用.
中介者类似于电脑主板,主板接着显示器,硬盘键盘等等设备,设备之间的通信全部经过主板协调.
在 Android 中的 Binder 驱动也是一个中介者,所有的 Service 在通信之前都会向 ServiceManger 查询出目标 Service,也就是说,进程直接不是直接跨进程,而是由 ServiceManager 来管理的.所以说 Binder 启动就是一个中介者模式.
17. 代理模式
定义:为其他类提供一种代理以控制这个对象的访问.
AIDL 文件会生成一个代理类,在跨进程通信传递数据时,Parcelable 对象的序列化与 transct 写入对方进程的内存地址,这一系列的操作都被代理类进行了隐藏.所以代理模式能很好的隐藏一些复杂的操作.
18. 组合模式
定义:将对象组成树形结构,以表示 "部分 - 整体" 的层次结构,使得用户对单个对象和组合对象的使用具有一致性.
Android 中的 ViewGroup 便是树形结构,每个 ViewGroup 包含一系列 View,而 ViewGroup 本身就是 View.这便是组合模式.
19. 适配器模式
定义:把一个类的接口变换成客户端所期待的另一个接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作.
适配器使用的频率特别高,每个 ListView 和 RecycleView 都需要适配器来给出每个 ItemView.至于如何给出 ItemView,可能不尽相同,但是 Adapter 给出了一个统一的接口规范,只需要进行一次转换即可.
20. 装饰模式
定义:动态的给一个对象添加额外的指责.就增加功能来说,装饰模式比子类集成的方式更灵活.
Android 中的 ContextWrapper(ContextThemeWrapper 的父类 (Acrtivity 的父类)).是一个地地道道的装饰者
21. 享元模式
public class ContextWrapper extends Context {
Context mBase;
// 由构造函数传入一个content
public ContextWrapper(Context base) {
mBase = base;
}
}
定义:使用享元对象有效地支持大量的细粒度对象.
享元可以说一直都在被使用,比如 Java 的常量池,线程池等.主要是为了重用对象.
在 Android 中,Handler 机制中有个 postMessage 方法,可以通过 Message.obtain() 来从消息池中取出可复用 Message,避免产生大量 Message 对象.
22. 外观模式
定义:要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行.
外观模式核心在于子系统与外部通信,比如当你 sendBroadcast,startActivity,bindService 等等,系统内部的实现非常复杂,但是一个统一的对象 context 把子系统全部隐藏起来.
23. 桥接模式
定义:将抽象部分与实现部分分离,使他们独立地进行变化.
一个类在多个维度上要进行变化,比如列表 View 在列表如何展示与数据来源上的两个维度的变化.具体来说就是 AbsListView 的两个维度的变化,AbsListView 的子类有 ListView,GridView,CustomListView 等等,而 ListAdapter 也是一个变化的维度.
24. MVC,MVP,MVVM 等组合设计模式
MVC
全称是 Model-View-Controller,如下图:
MVC 模式
在 Android 下,layout.xml 就是 View 层.数据层可以由数据库与网络数据构成 Model,但 Model 层要完全表达数据的输入与输出.Activity 就是 Controller 层,在比较复杂的 Activity 中,往往不能很好的完成表达成 Controller 层,往往混合了 View 层代码与 Model 层代码,这也是 Activity 的尴尬之处.
MVP
Model-View-Presenter,如下图:
mvp 模式
这个模式主要是为了解决 Activity 在 MVC 模式下的尴尬处境,把 Activity 完全表示为一个 View 层.这样 Activity 就可以很单纯的处理 View 的问题了,处理 View 显示问题也是 Activity 的特长.
MVVM
Model-View-ViewModel,如下图:
MVVM 模式
这个模式优化的显示层的问题,View 单向的访问 ViewModel,ViewModel 与 Model 之间进行交互.在 RecycleView 中的 ViewHolder 正是这种模式.
来源: http://www.jianshu.com/p/906701e988d1