[ 转载 ] Android设计模式详解

从Android再来认识23种设计模式

96 
ReadyShow 
 0.2 2018.01.06 23:18* 字数 3855 阅读 2584评论 0

概况来看本文章的内容

建立型:5个

单例模式
Builder
原型模式
工厂方法
抽象工厂java

行为型: 11个

策略模式
状态模式node

观察者模式
中介者模式
访问者模式
迭代器模式
模板方法算法

备忘录模式
命令模式
解释器模式
职责链模式数据库

结构型:7个

组合模式
代理模式
装饰模式
外观模式设计模式

享元模式
桥接模式
适配器模式安全

关于面向对象

面向对象的六大原则

谈到设计模式,不得不说说面向对象的六大原则网络

1. 单一原则

单一原则通俗的讲就是一个类只表达一个概念、一个方法只作一件事情。将一组相关性很高的函数、数据封装到一个类中。换句话说,一个类应该有职责单一。数据结构

2. 开闭原则

开闭原则就是一个类对于扩展是开发的,可是对于修改是封闭的。这也是六大原则中最难的,一般开闭都是短暂的美好,但在业务升级与拓展的状态下,原理的开闭是没法知足。即便是这样,也要尽量的扩展而不是修改。多线程

3. 里氏替换原则

全部引用基类的地方必须能透明地使用其子类对象。看着定义非常抽象,可是通俗的理解就是由子类实例化的父类引用,在使用这个引用时,感受就像是使用了父类同样。一个简单的例子:并发

public class T{ private class A{...} class B extends A{...} public static void main(String[] args){ A a = new B(); // 类型是A,但实际是B类型实例化的 a.method(); } } 

4. 依赖倒置原则

依赖倒置主要是为了解耦。具体来讲:

  1. 高层模块不该该依赖底层模块,两者都应该依赖其抽象
  2. 抽象不该该依赖细节
  3. 细节应该依赖抽象

5. 接口隔离原则

类之间的依赖关系应该创建在最小的接口上其原则是将繁杂的功能接口拆分红更加单一职责的接口,防止接口内部的耦合。

6. 迪米特原则

一个对象应该对其余的对象有最少的了解 保留关键的共有方法,其余次要的都是私有方法,不该该被外部了解。

Android来表达面向对象的六大原则

1. 单例模式

定义:确保单例类只有一个实例,而且这个单例类提供一个函数接口让其余类获取到这个惟一的实例。

单例模式的意义是显而易见的,能极大的节省资源,提升代码运行效率。缺点也是很明确的,就是不能发生状态的变化,以提供统一的功能。

单例模式有懒汉式与饿汉式,实现方式有静态成员变量法、枚举法、容器法等。单例须要注意的就是懒汉模式下的多线程安全问题。这里给出懒汉模式比较优雅的实现代码,其原理就是类加载器ClassLoader保证了并发的安全性。

public class Singleton{ private Singleton(){} public static synchronized Singleton getInstance() { return SingletonHolder.instance; } private static class SingletonHolder{ private static final Singleton instance = new Singleton(); } } 

Android系统下的单例模式有

//获取WindowManager服务引用 WindowManager wm = (WindowManager)getSystemService(getApplication().WINDOW_SERVICE); 

2. 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(); 

从上述代码中能够很是直观的看出Builder模式就是先设置好各类参数,而后再经过一个方法的调用构建出来一个复杂的对象。

3. 原型模式

原型模式很简单,使用一个实例拷贝后的实例。
在java中拷贝存在深拷贝与浅拷贝,若是类中的成员变量都是基本数据类型,则系统自动实现这些基本数据类型的深拷贝。
那什么时候要用到原型模式呢?防止本身的实例在传入别的模块后,发生意外的修改。进行一次拷贝,再将该实例当作参数传递给别人,是很是明智的操做,尤为是这个实例是某个类的成员变量。

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") ... 

4. 工厂方法模式

定义:定义一个建立对象的接口,让子类决定实例化哪一个类

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(); } } 

Android下的例子有BitmapFactory

public class BitmapFactory { public static Bitmap decodeFile(String pathName, Options opts) { Bitmap bm = null; ...... return bm; } } 

5. 抽象工厂模式

定义:为建立一组相关或者是相互依赖的对象提供一个接口,而不须要制定他们的具体类

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 简单工厂

这并非一个真正的模式,可是和抽象工厂和工厂方法模式同样,它常常被用于封装建立对象的代码

// 根据传入的参数决定给出哪一个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); } 

6. 策略模式

定义:有一系列的算法,将每一个算法封装起来(每一个算法能够封装到不一样的类中),各个算法之间能够替换,策略模式让算法独立于使用它的客户而独立变化。

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);} } 

Android的属性动画中使用时间插值器,就是策略模式。

7. 状态模式

容许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。

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(); } } 

状态模式在Android下使用的仍是不少的,好比WIFI在开启时,自动扫描周围的接入点,而后以列表展现,当WIFI关闭时,清空列表。

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也是迭代器模式

cursor = database.query(...);
while(cursor.moveToNext()){ cursor.get...; } 

14. 模板方法模式

定义:定义一个操做中的算法框架,而将一些步骤延迟到子类中,使得子类能够不改变一个算法的结构便可重定义该算法的某些特定的步骤。

直接看代码

public class CustomActivity extends Activity { // Activity留给用户自定义某些特定步骤 protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); // ... ... } } 

能够看出模板方法就是留出适当的方法等待子类来实现。无论如何重写父类,父类的主逻辑将不会被改变。

15. 访问者模式

定义:封装一些做用于某些数据结构中各元素的操做,它能够在不改变这个数据的前提下定义做用于这些元素的新的操做。

Android中不多使用访问者模式,ButterKnife中到是使用了。
这里只给出一个案例:
场景:一群人到你家,一块儿喂食宠物

  1. 抽象宠物角色(被访问者):动物抽象类
  2. 抽象访问者角色(访问者):给宠物喂食的人
  3. 具体被访问者:狗,猫
  4. 结构对象角色:主人家
  5. 具体访问者:主人、其余人

下面就具体来看实现:

  1. 建立抽象节点--宠物
interface Animal { void accept(Person person); } 
  1. 建立抽象访问者接口
interface Person { void feed(Cat cat); void feed(Dog dog); } 
  1. 建立Animal接口的具体节点
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("喵喵"); } } 
  1. 建立具体访问者角色
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("客人喂食狗");} } 
  1. 具体的结构对象,访问者与被访问者的交互空间,准确地说是Person访问Animal
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);} } } 
  1. 最后进行测试
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); } } 

16. 中介者模式

定义:中介者模式包装了一系列对象相互做用的方式,使得这些对象不
必相互明显调用,从而使他们能够轻松解耦。当某些对象之间的做用发生改变时,不会当即影响其余的一些对象之间的做用,保证这些做用能够彼此独立的变化,中介者模式将多对多的相互做用转为一对多的相互做用。

中介者相似于电脑主板,主板接着显示器,硬盘键盘等等设备,设备之间的通讯所有通过主板协调。

在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的父类))。是一个地地道道的装饰者

public class ContextWrapper extends Context { Context mBase; // 由构造函数传入一个content public ContextWrapper(Context base) { mBase = base; } } 

21. 享元模式

定义:使用享元对象有效地支持大量的细粒度对象。

享元能够说一直都在被使用,好比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正是这种模式。

相关文章
相关标签/搜索