目录
面对对象三大特征
封装 继承 多态 万事万物皆可为对象
封装
1、良好的封装能够减少耦合。
2、类内部的结构可以自由修改。
3、可以对成员进行更精确的控制。
4、隐藏信息,实现细节。
优点:方便修改类的内部实现,无需修改客户端的代码。就可以对成员变量进行更精确的控制。
继承
总结一点:代码复用
多态
概念:类的对象对同一消息作出不同的响应,这些不同类要么是继承了相同的父类,要么是实现了相同的接口
作用:解耦,各种设计模式的基础
条件:子类重写父类的方法
实现同一接口
使用父类或接口类型来引用子类或接口的实现类
例外情况:static方法,因为被static修饰的方法是属于类的,而不是属于实例的
final修饰的方法,不能被子类不重写
private修饰的方法,对子类不可见,更不能被重写
protected修饰的方法,虽然子类可见也能重写,但不能再外部引用
分类:编译时多态 方法的重载
运行时多态 方法的重写
为什么要学习设计模式?
设计模式(Design pattern)代表了最佳的实践,是很多优秀的软件开发人员的经验总结,是解决特定问题的解决方案。它并不是语法规定,也不拘泥于特定语言。 恰当的使用设计模式可以代码的可复用性,可维护性,可扩展性,健壮性及安全性,这些都是系统非常重要的非功能性需求。
设计模式的广泛使用起始于1995年,GOF(四人帮)出版的《设计模式:可复用面向对象软件基础》。
本部分相关的示例代码
https://gitee.com/lisenaq/patterndemo.git
oop设计原理
开闭原则
- 对扩展开放
- 对修改关闭
- 是所有原则的总目标
里氏替换原则
- 子类应当可以替换父类并出现在父类能够出现的地方
- 是多态的基础
迪米特原则(最少知识原则)
- 只与你的直接朋友交谈,不与"陌生人"说话
- 优点:其目的是降低类之间的耦合度,提高模块的相对独立性
- 缺点:过度使用迪米特法则会使系统产生大量的中介类,从而增加系统的复杂性
单一职责原则(DIP)
- 类不要承担太多的功能,职责要单一
- 如果承担太多功能,则每个功能的变化都会影响该类
接口分离原则(ISP)
- 客户端不应依赖它不需要的接口
- 可以理解为接口要符合单一职责原则
依赖倒置原则
- 高层模块不应该依赖底层模块,二者都应该依赖抽象
- 抽象不依赖于具体,具体依赖于抽象
- 中心思想是面向接口编程
- 为什么? 细节的东西往往是多变的,而越抽象则越稳定
组合/聚合复用原则
如果处于代码复用的目的,则应该使用组合/聚合复用原则,而不要使用继承
常见的设计原理
1.1单例模式
保证在内存中只用一个实例
使用场景
比如:系统配置文件的管理,这些配置文件只要使用一个单例对象进行读写即可,系统总其他地方需要使用配置信息时,只要使用该单例对象进行获取就可以了,这样便于统一管理配置信息。
优缺点
优点:
- 在内存中只有一个对象,节省内存空间;
- 避免频繁的创建销毁对象,可以提高性能;
- 避免对共享资源的多重占用,简化访问;
- 为整个系统提供一个全局访问点。
缺点:
- 不适用于变化频繁的对象;
- 滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;
1.2示例:
1.3饥饿模式
/**
* 单例模式,饥饿加载
*/
public class SingletonDemo {
//1. 需要有一个私有的构造函数,防止该类通过new的方式创建实例
private SingletonDemo(){}
//2. 饥饿模式,首先生成一个实例
private static final SingletonDemo instance = new SingletonDemo();
//3. 静态方法,用于获取已经生成的实例
public static SingletonDemo getInstance() {
return instance;
}
public String hello(String name) {
return "hello " + name;
}
}
这种直线方式简单,且是线程安全的。
1.4懒汉模式
第一种写法:
/**
* 单例模式: 懒汉式
*/
public class SingletonDemo02 {
private SingletonDemo02(){}
private static SingletonDemo02 singletonDemo02 = null;
public static SingletonDemo02 getInstance() {
if (singletonDemo02 == null) {
singletonDemo02 = new SingletonDemo02();
}
return singletonDemo02;
}
public String hello(String name) {
return "hello " + name;
}
}
注意: 这种方式在多线程访问时会有问题。
第二张写法:
/**
* 单例模式: 懒汉式,线程安全,但性能较低
*/
public class SingletonDemo03 {
private SingletonDemo03() {
}
private static SingletonDemo03 singletonDemo03 = null;
public static synchronized SingletonDemo03 getInstance(){
if(singletonDemo03 == null) {
singletonDemo03 = new SingletonDemo03();
}
return singletonDemo03;
}
public String hello(String name) {
return "hello " + name;
}
}
第三种写法:
public class SingletonDemo03 {
private SingletonDemo03() {
}
private static SingletonDemo03 singletonDemo03 = null;
public static SingletonDemo03 getInstance(){
//系统减小同步块来提升性能,可以吗?
if(singletonDemo03 == null) {
synchronized (SingletonDemo03.class) {
singletonDemo03 = new SingletonDemo03();
}
}
return singletonDemo03;
}
public String hello(String name) {
return "hello " + name;
}
}
注意:该方式依然会有线程安全问题
第四种写法:
/**
* 单例模式: 懒汉式,双重检查单例
*/
public class SingletonDemo03 {
private SingletonDemo03(){
}
private static SingletonDemo03 singletonDemo03 = null;
public static SingletonDemo03 getInstance(){
//减小同步块,并使用双重检查来保证线程安装,可以吗?
if(singletonDemo03 == null) {
synchronized (SingletonDemo03.class) {
if(singletonDemo03 == null) {
singletonDemo03 = new SingletonDemo03();
}
}
}
return singletonDemo03;
}
public String hello(String name) {
return "hello " + name;
}
}
第五种写法:
/**
* 单例模式: 懒加载, 线程安全
*/
public class SingletonDemo04 {
//阻止外部实例化
private SingletonDemo04(){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//使用静态内部类来使用一个SingletonDemo04对象
private static class SingletonDemoHolder {
private final static SingletonDemo04 instance = new SingletonDemo04();
}
public static SingletonDemo04 getInstance() {
return SingletonDemoHolder.instance;
}
public String hello(String name) {
return "hello " + name;
}
}
第六种写法:
public enum SingletonDemo05 {
INSTANCE;
public String hello(String name) {
return "hello " + name;
}
}
注意:可以保证单例,且线程安全
2.工厂模式
2.2.1 概念
用于产生对象的方法或者式类,称之为工厂。 上面所讲到的单例模式也可以看作为一个特殊的工厂。
2.2.2 使用场景
为什么需要工作模式,原来使用new的方式感觉也很简单,且好懂?
使用工厂的原因是我们可以通过工厂模式,来集中控制对象的创建过程,这样可以给设计带来更多的灵活性。
比如:spring的IOC容器就是工厂模式的经典实现。
2.2.3 工厂方法
用于生产指定系列的对象。已鸭子为例,鸭子有真的鸭子,橡皮鸭,电子玩具鸭等。如何能方便的创建出各种鸭子,并将创建过程控制起来,以便于以后的维护和扩展?
类图:
2.2.4 抽象工厂
用于生成指定产品族,一个产品族中包括多种产品。例如:
我们都比较熟悉的电脑制造相关行业,有HP,罗技,联想,戴尔,近几年华为,小米也进来了,每个生产商生产的电脑又包括鼠标,键盘,屏幕等等配件。此时我们需要使用工厂模式来进行管理不同的产品族,这时使用简单工厂(也有叫作工厂方法的)已经无法满足要求,此时可以使用抽象工厂。
类图:
2.3 责任链模式
2.3.1 概念
责任链模式是一个对象的行为模式,很多对象之间形成一条链条,处理请求在这个链条上进行传递,直到责任链的上的某个对象决定处理请求(也可扩展为几个对象处理),这个过程对于用户来说是透明的,也就是说用户并不需要知道是责任链上的哪个对象处理的请求,对请求是否处理由链条上的对象自己决定。
为了便于理解我们可以想象一下击鼓传花的游戏。
2.3.2 使用场景
web容器中的过滤器算是责任链模式的一个经典场景。另外举个例子:当在论坛上提交内容时,论坛系统需要对一些关键词进行处理,看看有没有包含一些敏感词汇,而这些敏感词汇我们可以使用责任链模式进行处理。
2.3.3 类图
2.4 观察者模式(Obsever)
2.4.1 概念
观察者模式是对象的行为模式,有时也称为“发布/订阅模式”或者“监听器模式”。
观察者模式定义了观察者和被观察者之间的一点多的关系,让多个观察者对象可以响应一个被观察者对象。
2.4.2 使用场景
比较经典的使用场景,比如:java中的swing包中对事件的处理。浏览器对鼠标,键盘等事件的处理等, spring中的事件发布机制也是使用该模式。
2.4.3 类图
2.4.4 小结
观察者模式是使用的非常广泛,比如:Listener,Hook,Callback等等,其实都是观察者的一种应用,名称叫法不同而已,思路基本相同。