- UID
- 1029342
- 性别
- 男
|
谈谈23种设计模式在Android项目中的应用
用这种方式进行介绍设计模式,旨在结合每天都在接触的Android实际项目开发更好地理解设计模式,拉近与设计模式的距离,同时在实际开发与重构中,思考可以应用的重构手段与设计模式,既能保证写出复用性与可靠性更高的代码,也是对如何利用重构与设计模式这两大支柱进行优雅编程的最佳实践与总结。
作者:林炳河来源:林炳河|2017-03-20 18:03
移动端
收藏
分享
前言
本文将结合实际谈谈23种设计模式,每种设计模式涉及
定义:抽象化的定义与通俗的描述,尽量说明清楚其含义与应用场景
示例:如果项目中有使用过该模式,则会给出项目中的代码,否则会给出尽可能简单好理解的java代码
Android:该设计模式在Android源码框架中哪些地方有使用到
重构:项目中是否存在可以用该模式进行重构的地方,如果有会给出重构前与重构后的代码或者思路
用这种方式进行介绍设计模式,旨在结合每天都在接触的Android实际项目开发更好地理解设计模式,拉近与设计模式的距离,同时在实际开发与重构中,思考可以应用的重构手段与设计模式,既能保证写出复用性与可靠性更高的代码,也是对如何利用重构与设计模式这两大支柱进行优雅编程的最佳实践与总结。
同时一次性以这种方式介绍23种设计模式,也是出于既然要使用一个模式,那么就应该要先知道这么一个模式的想法,四人帮的《设计模式》也是对经验的总结,但是有巨人托着你上去,又何必自己再摸黑造梯子。
重构不是本章的重点,因为这也是一个非常大的话题,这边只讨论实际项目中是否有存在一些能用设计模式进行改善的地方。
关于重构,这边也有写了一篇博文 重构:改善既有代码的设计 ,基本列举了《重构:改善既有代码的设计》中的各项要点,后续还会继续将《重构》中的手法与设计模式应用到实际项目中,有所总结之后会再写几篇实际应用的博文。
简介
设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是它能被广泛应用的原因。
六大原则
单一职责原则
单一原则很简单,就是将一组相关性很高的函数、数据封装到一个类中。换句话说,一个类应该有职责单一。
开闭原则
开闭原则理解起来也不复杂,就是一个类应该对于扩展是开放的,但是对于修改是封闭的。在一开始编写代码时,就应该注意尽量通过扩展的方式实现新的功能,而不是通过修改已有的代码实现,否则容易破坏原有的系统,也可能带来新的问题,如果发现没办法通过扩展来实现,应该考虑是否是代码结构上的问题,通过重构等方式进行解决。
里氏替换原则
所有引用基类的地方必须能透明地使用其子类对象。本质上就是说要好好利用继承和多态,从而以父类的形式来声明变量(或形参),为变量(或形参)赋值任何继承于这个父类的子类。
依赖倒置原则
依赖倒置主要是实现解耦,使得高层次的模块不依赖于低层次模块的具体实现细节。怎么去理解它呢,我们需要知道几个关键点:
高层模块不应该依赖底层模块(具体实现),二者都应该依赖其抽象(抽象类或接口)
抽象不应该依赖细节
细节应该依赖于抽象
在我们用的Java语言中,抽象就是指接口或者抽象类,二者都是不能直接被实例化;细节就是实现类,实现接口或者继承抽象类而产生的类,就是细节。使用Java语言描述就是:各个模块之间相互传递的参数声明为抽象类型,而不是声明为具体的实现类;
接口隔离原则
类之间的依赖关系应该建立在最小的接口上。其原则是将非常庞大的、臃肿的接口拆分成更小的更具体的接口。
迪米特原则
一个对象应该对其他的对象有最少的了解.
假设类A实现了某个功能,类B需要调用类A的去执行这个功能,那么类A应该只暴露一个函数给类B,这个函数表示是实现这个功能的函数,而不是让类A把实现这个功能的所有细分的函数暴露给B。
设计模式
单例模式
定义
确保单例类只有一个实例,并且这个单例类提供一个函数接口让其他类获取到这个唯一的实例。
如果某个类,创建时需要消耗很多资源,即new出这个类的代价很大;或者是这个类占用很多内存,如果创建太多这个类实例会导致内存占用太多。上述情况下就应该使用单例模式
实际应用
// 单例对象
private static AdvertPresenter mInstance;
/** * 私有化构造函数 */
private AdvertPresenter(){
}
/** * 获取AdvertPresenter实例 * @return */
public static AdvertPresenter getInstance() {
if (mInstance == null) {
synchronized (AdvertPresenter.class) {
if (mInstance == null) {
mInstance = new AdvertPresenter();
}
}
}
return mInstance;
}
Android
//获取WindowManager服务引用
WindowManager wm = (WindowManager)getSystemService(getApplication().WINDOW_SERVICE);
其内部就是通过单例的方式持有一个WindowManager并返回这个对象
重构
项目中存在多次使用Random与Gson的操作,可以将Random与Gson对象封装成单例进行使用
建造者模式
定义
将一个复杂对象的构造与它的表示分离,使得同样的构造过程可以创建不同的表示。
主要是在创建某个对象时,需要设定很多的参数(通过setter方法),但是这些参数必须按照某个顺序设定,或者是设置步骤不同会得到不同结果。
示例
各类自定义Dialog
Android
AlertDialog.Builer builder=new AlertDialog.Builder(context);
builder.setIcon(R.drawable.icon)
.setTitle("title")
.setMessage("message")
.setPositiveButton("Button1",
new DialogInterface.OnclickListener(){
public void onClick(DialogInterface dialog,int whichButton){
setTitle("click");
}
})
.create()
.show();
重构
暂无
原型模式
定义
用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。
可以在类的属性特别多,但是又要经常对类进行拷贝的时候可以用原型模式,这样代码比较简洁,而且比较方便。
拷贝时要注意浅拷贝与深拷贝
示例
private HashMap getClonePointMap(Map map) {
HashMap clone = new HashMap<>();
if (map != null) {
Iterator iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry entry = (Map.Entry) iterator.next();
String key = (String) entry.getKey();
PointBean pointBean = (PointBean) entry.getValue();
if (pointBean != null) {
//遍历map并将克隆对象放到新的map中
clone.put(key, pointBean.clone());
} else {
clone.put(key, null);
}
}
}
return clone;
}
Android
Intent intent = new Intent(Intent.ACTION_SENDTO, uri);
//克隆副本
Intent copyIntent=(Intetn)shareIntent.clone();
重构
如果存在逐一去除某个对象的各项参数值,转而赋值给另一个对象身上时,便可使用原型模式 |
|