面向对象设计原则
1. 单一职责原则
一个类只负责一个功能领域中的相应职责,或者可以定义为:就一个类而言,应该只有一个引起它变化的原因(实现高内聚、低耦合)
2. 开闭原则
一个类应该对扩展开放,对修改封闭(抽象化是开闭原则的关键,可以定义一个相对稳定的抽象层,而将不同的实现行为移至具体的实现层中完成)
3. 里氏代换原则
所有引用基类(父类)的地方必须能透明地使用其子类的对象,里氏代换原则是实现开闭原则的重要方式之一,由于使用基类对象的地方都可以使用子类对象,因此在程序中尽量使用基类类型来对对象进行定义,而在运行时再确定其子类类型,用子类对象来替换父类对象
例如 DeomAdapter 构造方法接受List,凡是实现List接口的类都可以作为参数1
2
3
4
5
6
7public class DemoAdapter {
public DemoAdapter(List<String> data){
}
}
public XXXList<E> implements List<E> {
}
4. 依赖倒转原则
抽象不应该依赖于细节,细节应当依赖于抽象。换言之,要针对接口编程,而不是针对实现编程,依赖倒转原则要求我们在程序代码中传递参数时或在关联关系中,尽量引用层次高的抽象层类,即使用接口和抽象类进行变量类型声明、参数类型声明、方法返回类型声明,以及数据类型的转换等,而不要用具体类来做这些事情, 例子同上
5. 接口隔离原则
使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口(呼应单一职责原则)
6. 合成复用原则
尽量使用对象组合,而不是继承来达到复用的目的,在面向对象设计中,可以通过两种方法在不同的环境中复用已有的设计和实现,即通过组合/聚合关系或通过继承,但首先应该考虑使用组合/聚合,组合/聚合可以使系统更加灵活,降低类与类之间的耦合度,一个类的变化对其他类造成的影响相对较少
7. 迪米特法则(最少知识原则)
一个软件实体应当尽可能少地与其他实体发生相互作用,迪米特法则要求我们在设计系统时,应该尽量减少对象之间的交互,如果两个对象之间不必彼此直接通信,那么这两个对象就不应当发生任何直接的相互作用,如果其中的一个对象需要调用另一个对象的某一个方法的话,可以通过第三者转发这个调用
设计模式分类
创建型模式 (6个)
- 简单工厂模式-Simple Factory Pattern
- 工厂方法模式-Factory Method Pattern
- 抽象工厂模式-Abstract Factory Pattern
- 单例模式-Singleton Pattern
- 原型模式-Prototype Pattern
- 建造者模式-Builder Pattern
结构型模式(7个)
- 适配器模式-Adapter Pattern
- 桥接模式-Bridge Pattern
- 组合模式-Composite Pattern
- 装饰模式-Decorator Pattern
- 外观模式-Facade Pattern
- 享元模式-Flyweight Pattern
- 代理模式-Proxy Pattern
行为型模式(11个)
- 职责链模式-Chain of Responsibility Pattern
- 命令模式-Command Pattern
- 解释器模式-Interpreter Pattern
- 迭代器模式-Iterator Pattern
- 中介者模式-Mediator Pattern
- 备忘录模式-Memento Pattern
- 观察者模式-Observer Pattern
- 状态模式-State Pattern
- 策略模式-Strategy Pattern
- 模板方法模式-Template Method Pattern
- 访问者模式-Visitor Pattern
常用设计模式
创建型模式
1 . 简单工厂模式
定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。因为在简单工厂模式中用于创建实例的方法是静态(static)方法,因此简单工厂模式又被称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24public class FragmentFactory {
public static final int DISPLAY_TEST_COMMON_ACTIVITY = 1;
public static final int DISPLAY_XXX_XXX = 2;
/**
* 根据参数创建相应的fragment
*
* @param displayType
* @return
*/
public static BaseFragment createFragment(int displayType) {
switch (displayType) {
case DISPLAY_TEST_COMMON_ACTIVITY:
return new PcSceneFragment();
case DISPLAY_XXX_XXX:
return new XXXFragment();
default:
break;
}
return null;
}
}
2 . 工厂方法模式
工厂方法模式中,我们不再提供一个统一的工厂类来创建所有的产品对象,而是针对不同的产品提供不同的工厂,系统提供一个与产品等级结构对应的工厂等级结构
可以通过配置文件来存储具体工厂类ConcreteFactory的类名,更换新的具体工厂时无须修改源代码,系统扩展更为方便
3 . 抽象工厂模式
抽象工厂模式为创建一组对象提供了一种解决方案。与工厂方法模式相比,抽象工厂模式中的具体工厂不只是创建一种产品,它负责创建一族产品(应用场景:换主题)
工厂模式的作用:
将对象的创建和使用分离,使用者不需要关心对象创建的具体过程
防止对象创建的代码在多个类中到处都是,造成代码重复及维护困难,如果创建过程只在工厂类中,只需要修改工厂类一个类,其他使用该对象的类不需要改动
ref: http://blog.csdn.net/lovelion/article/details/7523392
4 . 单例模式
饿汉模式:1
2
3
4
5
6
7
8
9
10public class Singleton {
private static Singleton instance = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return instance;
}
}
懒汉模式:1
2
3
4
5
6
7
8
9
10
11
12
13public class Singleton {
private static Singleton instance;
private Singleton() {
}
public static Singleton getInstance() {
if (null == instance){
instance = new Singleton();
}
return instance;
}
}
静态内部类:1
2
3
4
5
6
7
8
9
10
11
12public class Singleton {
private Singleton() {
}
public static Singleton getInstance() {
return SingletonHolder.instance;
}
private static class SingletonHolder {
private static Singleton instance = new Singleton();
}
}
枚举实现单例:1
2
3public enum Singleton {
INSTANCE
}
可以使用Singleton.INSTANCE调用
单例的作用:
节省多次创建对象的开销
节省内存
5 . 原型模式
使用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象
Java中可以直接使用Object提供的clone()方法来实现对象的克隆,Java语言中的原型模式实现很简单,需要注意的是能够实现克隆的Java类必须实现一个标识接口Cloneable,表示这个Java类支持被复制。如果一个类没有实现这个接口但是调用了clone()方法,Java编译器将抛出一个CloneNotSupportedException异常1
2
3
4
5
6
7
8
9
10
11
12
13class ConcretePrototype implements Cloneable{
……
public Prototype clone(){
Object object = null;
try {
object = super.clone();
} catch (CloneNotSupportedException exception) {
System.err.println("Not support cloneable");
}
return (Prototype )object;
}
……
}
6 . 建造者模式
EventBus1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49public class EventBusBuilder {
private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();
boolean logSubscriberExceptions = true;
boolean logNoSubscriberMessages = true;
boolean sendSubscriberExceptionEvent = true;
boolean sendNoSubscriberEvent = true;
boolean throwSubscriberException;
boolean eventInheritance = true;
boolean ignoreGeneratedIndex;
boolean strictMethodVerification;
ExecutorService executorService = DEFAULT_EXECUTOR_SERVICE;
List<Class<?>> skipMethodVerificationForClasses;
List<SubscriberInfoIndex> subscriberInfoIndexes;
EventBusBuilder() {
}
......
/** Default: true */
public EventBusBuilder logSubscriberExceptions(boolean logSubscriberExceptions) {
this.logSubscriberExceptions = logSubscriberExceptions;
return this;
}
/** Default: true */
public EventBusBuilder logNoSubscriberMessages(boolean logNoSubscriberMessages) {
this.logNoSubscriberMessages = logNoSubscriberMessages;
return this;
}
/** Default: true */
public EventBusBuilder sendSubscriberExceptionEvent(boolean sendSubscriberExceptionEvent) {
this.sendSubscriberExceptionEvent = sendSubscriberExceptionEvent;
return this;
}
/** Default: true */
public EventBusBuilder sendNoSubscriberEvent(boolean sendNoSubscriberEvent) {
this.sendNoSubscriberEvent = sendNoSubscriberEvent;
return this;
}
......
/** Builds an EventBus based on the current configuration. */
public EventBus build() {
return new EventBus(this);
}
}
1 | public EventBus() { |
1 | EventBus(EventBusBuilder builder) { |
Builder模式好处:
创建对象时可以灵活的配置对象属性
代码优雅
结构型模式
1 . 适配器模式
与电源适配器相似,在适配器模式中引入了一个被称为适配器(Adapter)的包装类,而它所包装的对象称为适配者(Adaptee),即被适配的类。适配器的实现就是把客户类的请求转化为对适配者的相应接口的调用
Android中ListView、GridView的Adapter
2 . 组合模式
组合多个对象形成树形结构以表示具有“整体—部分”关系的层次结构。组合模式对单个对象(即叶子对象)和组合对象(即容器对象)的使用具有一致性,组合模式又可以称为“整体—部分”(Part-Whole)模式,提供一个统一的方法访问对象
Android中的应用:
3 . 装饰器模式(Wrapper 模式)
动态地给一个对象增加一些额外的职责,就增加对象功能来说,装饰模式比生成子类实现更为灵活;装饰模式是一种用于替代继承的技术,它通过一种无须定义子类的方式来给对象动态增加职责,使用对象之间的关联关系取代类之间的继承关系.
Android中的应用:
4 . 代理模式
给某一个对象提供一个代理或占位符,并由代理对象来控制对原对象的访问,代理模式是一种应用很广泛的结构型设计模式,而且变化形式非常多,常见的代理形式包括远程代理、保护代理、虚拟代理、缓冲代理、智能引用代理等
代理模式 VS 装饰器模式
代理可以对它的客户隐藏一个对象的具体信息,因此当使用代理时,我们通常在代理类中创建被代理的对象
使用装饰器模式时, 我们通常将原始对象作为参数传递给装饰者的构造器
5 . 外观模式(门面模式)
为子系统中的一组接口提供一个统一的入口。外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用
Android中的应用:
行为型模式
1 . 责任链模式
避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止
2 . 观察者模式
定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式的别名包括发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式
1 | public class DataSetObservable extends Observable<DataSetObserver> { |
1 | class AdapterDataSetObserver extends DataSetObserver { |
3 . 策略模式
定义一系列算法类,将每一个算法封装起来,并让它们可以相互替换,策略模式让算法独立于使用它的客户而变化,也称为政策模式(Policy)
Android中策略模式:
Java中的Comparator1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22private void testSort() {
long startTime = System.currentTimeMillis();
Map<String, Integer> map = new HashMap<>();
Random random = new Random();
for (int i = 0; i < 100000000; i++) {
map.put(String.valueOf(random.nextInt(100000)), random.nextInt(1000));
}
List<Map.Entry<String, Integer>> list = new ArrayList<>(map.entrySet());
Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() {
@Override
public int compare(Map.Entry<String, Integer> lhs, Map.Entry<String, Integer> rhs) {
return rhs.getValue().compareTo(lhs.getValue());
}
});
for (Map.Entry<String, Integer> entry : list) {
System.out.print(entry.getKey() + ":" + entry.getValue() + "\n");
}
long endTime = System.currentTimeMillis();
long duration = (endTime - startTime);
System.out.println(duration);
}
4 . 迭代器模式
提供一种方法来访问聚合对象,而不用暴露这个对象的内部表示,其别名为游标(Cursor)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18public interface Iterator<E> {
/**
* Returns true if there is at least one more element, false otherwise.
* @see #next
*/
public boolean hasNext();
/**
* Returns the next object and advances the iterator.
*/
public E next();
/**
* Removes the last object returned by {@code next} from the collection.
* This method can only be called once between each call to {@code next}.
*/
public void remove();
}
AbstractList中的一个迭代器1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48private class SimpleListIterator implements Iterator<E> {
int pos = -1;
int expectedModCount;
int lastPosition = -1;
SimpleListIterator() {
expectedModCount = modCount;
}
public boolean hasNext() {
return pos + 1 < size();
}
public E next() {
if (expectedModCount == modCount) {
try {
E result = get(pos + 1);
lastPosition = ++pos;
return result;
} catch (IndexOutOfBoundsException e) {
throw new NoSuchElementException();
}
}
throw new ConcurrentModificationException();
}
public void remove() {
if (this.lastPosition == -1) {
throw new IllegalStateException();
}
if (expectedModCount != modCount) {
throw new ConcurrentModificationException();
}
try {
AbstractList.this.remove(lastPosition);
} catch (IndexOutOfBoundsException e) {
throw new ConcurrentModificationException();
}
expectedModCount = modCount;
if (pos == lastPosition) {
pos--;
}
lastPosition = -1;
}
}
5 . 模板方法模式
定义一个操作中算法(行为方法)的框架,而将一些步骤延迟到子类中。模板方法模式使得子类可以不改变一个算法(行为方法)的结构即可重定义该算法的某些特定步骤1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45public abstract class BaseActivity<P extends BasePresenter> extends AppCompatActivity implements BaseView {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContext = this;
preLoad(); //钩子方法(hook)
setContentView(getRootView());
mPresenter = createPresenter();
if (null != mPresenter) mPresenter.attachView(this);
initData(savedInstanceState);
setListener();
}
/**
* 预加载,setContentView之前执行
*/
protected void preLoad() {
}
/**
* 获取布局id
*
* @return
*/
protected abstract int getRootView();
/**
* 创建View对应的Presenter
*
* @return
*/
protected abstract P createPresenter();
/**
* 初始化数据
* 根据数据设置view内容
*/
protected abstract void initData(Bundle savedInstanceState);
/**
* 设置监听
*/
protected abstract void setListener();
}
参考资料:
http://blog.csdn.net/lovelion/article/details/17517213
《Android源码设计模式实战》
Android/EventBus 等源码