前言:
面向对象具有三大基本特征,六大基本原则,二十三种设计模式。
三大基本特征:
- 封装
- 继承
- 多态
六大原则
- 单一职责原则
- 开闭原则
- 里氏替换原则
- 依赖倒置原则
- 接口隔离原则
- 迪米特原则
二十三种设计模式
- 单例模式
- Builder模式
- 原型模式
- 工厂方法模式
- 抽象工厂方法模式
- 策略模式
- 状态模式
- 责任链模式
- 解释器模式
- 命令模式
- 观察者模式
- 备忘录模式
- 迭代器模式
- 模板方法模式
- 访问者模式
- 中介者模式
- 代理模式
- 组合模式
- 适配器模式
- 装饰模式
- 亨元模式
- 外观模式
- 桥接模式。
一、 单一职责原则
英文名称为”Single Responsibility Principle”,缩写SRP。正如字面上所说,这一原则体现在“单一”二字,描述的是一个类的职责是单一的,与该类无关的功能或者完全不一样的功能不该出现在该类中,而需要将该类所具有的功能独立出来。而这个类中仅有的是一组相关性很高的函数,数据的封装。也就是说跟这个类不相关的函数,数据不能出现在这个类中,举个例子,以前我们写代码往往都是将所有的代码放在一个类中,尽管功能不同,这样会导致一个类的体积过于庞大,而且职责不明确,之后我们学会了编写工具类,将特定功能的代码抽取到一个工具类中,或是学会了mvc模式,model层的类负责加载数据的业务逻辑代码,view层的类负责界面视图的展示,control层的负责model与view的交互等等,各层的类职责很明确,这些都是在遵循单一职责的原则,这样一来使得一个类体积不会庞大,功能职责明确,遵循单一职责原则的封装才是正确的封装。
代码演示:
public class Cat{
public void zhualaoshu() {
System.out.println("猫抓老鼠!");
}
}
public class Dog{
public void shoujia() {
System.out.println("狗会守家!");
}
}
猫抓老鼠,狗呢守家就可以了,狗拿耗子的话就有点多管闲事了。
二、 开闭原则
英文名称为“Open Close Principle”,缩写OCP。开闭原则描述的是对象(类,模块,函数)对于扩展是开放的,对于修改是封闭的。当软件更新需要修改代码时,尽量通过扩展的方式来实现代码的更新,而不是通过修改已有的代码实现更新。而现实中比如google浏览器允许用户自己编写插件,实现一些特定的功能,但不能自己修改google浏览器,这有点类似开闭原则,对于扩展是开放的,对于修改是封闭的。又如我们在编写一个软件的时候,涉及到后台数据库可能会更换不同的实现,这个时候我们起初在设计的时候需要遵循开闭原则,将后台数据库的设计用面向接口编程实现,如我们熟悉的dao层,model层是通过接口进行交互的,这样一来,当我们替换后台数据库的实现,只需要替换具体的dao层实现类即可。开闭原则往往需要借助于抽象和接口,同时对于原有的代码要求尽量不要修改,不过,当原有的代码出现问题或是更不是时代潮流的时候,我们还是需要修改原有的代码的。
代码演示:
public class CyberFactory{
public void produce(Cyber cyber) {
System.out.println("工厂生产了:"+cyber.what());
}
public static void main(String[] args) {
CyberFactory cyberFactory = new CyberFactory();
cyberFactory.produce(new Phone());
cyberFactory.produce(new Computer());
}
}
interface Cyber{
public String what();
}
public class Computer implements Cyber{
@Override
public String what() {
return "电脑";
}
}
public class Phone implements Cyber{
@Override
public String what() {
return "手机";
}
}
当电子工厂需要生产新的电子产品的时候(扩展),只需要引进新产品的生产体系就可以了,而与原有产品无关。
三、 里氏替换原则
英文名称为“Liskov Substitution Principle”,缩写是LSP。里氏替换原则描述的是凡是父类能出现的地方,其子类就可以替换这个父类而不会产生任何的异常或错误,反之则不行。这让我们想到的是,一个变量的类型是父类,它可以被赋值为其父类的任何一个子类,强调了多态。里氏替换原则和开闭原则往往是一起被遵循的。
代码演示:
还是和开闭原则的代码差不多,这里对上面的代码稍加修改,即:
public class CyberFactory{
public void produce(Cyber cyber) {
System.out.println("工厂生产了:"+cyber.what());
}
public void call(Phone phone) {
phone.call();
}
public static void main(String[] args) {
CyberFactory cyberFactory = new CyberFactory();
cyberFactory.produce(new Phone());
cyberFactory.produce(new Computer());
}
}
public class Phone implements Cyber{
@Override
public String what() {
return "手机";
}
public void call() {
System.out.println("拨打电话");
}
}
工厂生产的电子产品可以用手机和电脑替代,但工厂打电话的时候只能通过手机打电话,尽管它有很多的电子产品。
四、 依赖倒置原则
英文名称为“Dependence Inversion Principle”,缩写是DIP。依赖倒置原则描述的是两个功能不一样的类通过它们的抽象来建立关系,而不依赖于它们具体的实现。一个类中的函数的功能有时候需要依赖另外一个类的函数来实现,这个时候就是两个不同类之间的交互了,如果不遵循一些原则的话耦合度会比较高,而遵循依赖倒置原则之后两个类之间的交互依赖于它们的抽象,当功能需要变更的时候,只需要更换另外一个类的具体实现就可以了。强调的是面向接口/抽象编程。
同开闭原则的代码,电子工厂的produce方法是CyberFactory类与Cyber类(接口)之间的交互,这里的交互依赖于抽象(参数是一个Cyber接口类型)而不是具体的实现(如手机或电脑)。
五、 接口隔离原则
英文名称为“InterfaceSegregation principles”,缩写是ISP。接口隔离原则描述的是客户端不应该依赖它不需要的接口,而类间的依赖应该建立在最小的接口上。
代码演示:
package Test;
import java.io.Closeable;
import java.io.IOException;
public final class CloseUtils{
/**
* 工具类一般将构造方法隐藏
*/
private CloseUtils() {
}
public static void closeQuietly(Closeable closeable) {
if (null != null) {
try {
closeable.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
这是一个工具类,其功能是将传进来的Closeable对象关闭,我们知道java中有100多个类实现了这个接口,常用的IO对象就实现了这个接口,每当我们用完了IO对象之后,我们都需要将它进行关闭,每次调用这个对象的close方法都需要捕获异常,这样一来就会显得比较繁琐,所以可以借助这个工具类来完成Closeable对象的关闭操作,而CloseUtils工具类是隔离接口的,因为它仅通过最小的接口Closeable接口,如对于OutputStream的一个对象则隔离了Flushable接口(不需要的接口则隔离)。
六、 迪米特原则
英文名称为“Law of Demeter”,缩写是LOD,也称之为最少知识原则。其描述的是一个类应该对自己需要耦合或调用的类知道得最少,类的内部如何实现与调用者或者依赖者没关系,调用者或者依赖者只需要知道它需要的方法即可。这个比较好理解,就是封装的目的一样,调用者只需要使用被调用者提供的方法一样,如工具类的使用。