面向对象的六大原则
参考 http://www.tuicool.com/articles/mqmYr2
http://blog.csdn.net/banketree/article/details/24985607
在Java以及其他的面向对象设计模式中,类与类之间主要有6种关系,他们分别是:依赖、关联、聚合、组合、继承、实现。它们的耦合度依次增强。
对象之间的关系
依赖:
对于两个相对独立的对象,当一个对象负责构造另一个对象的实例,或者依赖另一个对象的服务时,这两个对象之间主要体现为依赖关系。
关联:
分为单向关联和双向关联。在java中,单向关联表现为:类A当中使用了类B,其中类B是作为类A的成员变量。
双向关联表现为:类A当中使用了类B作为成员变量;同时类B中也使用了类A作为成员变量。
聚合:
是关联关系的一种,耦合度强于关联,他们的代码表现是相同的,仅仅是在语义上有所区别:
关联关系的对象间是相互独立的,而聚合关系的对象之间存在着包容关系,他们之间是“整体-个体”的相互关系。
组合:
是一种耦合度更强的关联关系。存在组合关系的类表示“整体-部分”的关联关系,
“整体”负责“部分”的生命周期,他们之间是共生共死的;并且“部分”单独存在时没有任何意义。
继承:
表示类与类(或者接口与接口)之间的父子关系。
实现:
表示一个类实现一个或多个接口的方法。
1.单一职责原则
单一职责原则的英文名称是Single Responsibility Principle,简称是SRP,简单来说一个类只做一件事。
这个设计原则备受争议却又及其重要的原则。
因为单一职责的划分界限并不是如马路上的行车道那么清晰,很多时候都是需要靠个人经验来界定。
当然最大的问题就是对职责的定义,什么是类的职责,以及怎么划分类的职责。
在Volley中,使用HttpStack接口解析网络请求就是一个典型的例子
/**
* An HTTP stack abstraction.
*/
public interface HttpStack {
/**
* 执行Http请求,并且返回一个HttpResponse
*/
public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders)
throws IOException, AuthFailureError;
}
优点:
类的复杂性降低,实现什么职责都有清晰明确的定义;
可读性提高,复杂性降低,那当然可读性提高了;
可维护性提高,可读性提高,那当然更容易维护了;
变更引起的风险降低,变更是必不可少的,如果接口的单一职责做得好,
一个接口修改只对相应的实现类有影响,对其他的接口无影响,这对系统的扩展性、维护性都有非常大的帮助。
2. 里式替换原则
简述
面向对象的语言的三大特点是继承、封装、多态,里氏替换原则就是依赖于继承、多态这两大特性。
里氏替换原则简单来说就是所有引用基类的地方必须能透明地使用其子类的对象。
通俗点讲,只要父类能出现的地方子类就可以出现,而且替换为子类也不会产生任何错误或异常,使用者可能根本就不需要知道是父类还是子类。
但是,反过来就不行了,有子类出现的地方,父类未必就能适应。
Volley类中的静态方法
public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR);
String userAgent = "volley/0";
// 代码省略
// 1、构造HttpStack对象
if (stack == null) {
if (Build.VERSION.SDK_INT >= 9) {
stack = new HurlStack();
} else {
// Prior to Gingerbread, HttpUrlConnection was unreliable.
// See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html
stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
}
}
// 2、将HttpStack对象传递给Network对象
Network network = new BasicNetwork(stack);
// 3、将network对象传递给网络请求队列
RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network);
queue.start();
return queue;
}
任何实现HttpStack接口的类的对象都可以传递给BasicNetwork实现网络请求的功能,
这样Volley执行网络请求的方法就有很多种可能性,而不是只有HttpClient和HttpURLConnection。
里式替换的思想是任何父类出现的地方子类都可以出现.
优点:
代码共享,减少创建类的工作量,每个子类都拥有父类的方法和属性;
提高代码的重用性;
提高代码的可扩展性,实现父类的方法就可以“为所欲为”了,很多开源框架的扩展接口都是通过继承父类来完成的;
提高产品或项目的开放性。
缺点:
继承是侵入性的。只要继承,就必须拥有父类的所有属性和方法;
降低代码的灵活性。子类必须拥有父类的属性和方法,让子类自由的世界中多了些约束;
增强了耦合性。当父类的常量、变量和方法被修改时,
必需要考虑子类的修改,而且在缺乏规范的环境下,这种修改可能带来非常糟糕的结果——大片的代码需要重构。
3.依赖倒置原则
在Java语言中,抽象就是指接口或抽象类,两者都是不能直接被实例化的;
细节就是实现类,实现接口或继承抽象类而产生的类就是细节,其特点就是可以直接被实例化,也就是可以加上一个关键字 new 产生一个对象。
依赖倒置原则在 Java 语言中的表现就是: 模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生的。
其实就是一句话:面向接口编程,或者说是面向抽象编程,这里的抽象指的是接口或者抽象类。面向接口编程是面向对象精髓之一。