一、面向对象的几个基本原则
1. 开-闭原则
核心:对扩展开放,对修改关闭。
要想达到这样的效果,需要使用接口和抽象类。
2. 里氏代换原则
子类继承父类时,除添加新的方法完成新增的功能外,不要重写父类的方法。
3. 合成复用原则
概念:尽量使用组合或聚合等来实现,其次才考虑使用继承关系来实现。
通常分为继承复用和合成复用两种。
- 继承复用:
优点:简单和易实现
缺点:父类对子类是透明的,也称“白盒”复用;子类和父类的耦合度高;限制了复用的灵活性。 - 合成复用:
优点:维持了类的复用性,也称“黑盒”复用;耦合度低;复用的灵活性高。
例如:Com是一个接口,接口中包含一个computer()方法。
public class Computer{
Com com;
public void setCom(Com com){
this.com = com;
}
public void f(){
com.computer();
}
}
- 多用组合,少用继承
4. 面向抽象原则
设计一个类时,不让该类面向具体的类,而是面向抽象类或接口。
二、UML类图简介
1. 泛化关系
泛化关系就是继承关系。
UML图:实线的起始端是子类,终点端是父类,终点端使用一个空心的三角形表示实线的结束。
2. 关联关系
A类中成员变量是用B类(接口)来声明的变量,那么A和B的关系是关联关系。
UML图:实线的起始端是A,实线的终点端是B,终点端使用一个指向B的方向箭头表示实线的结束。
3. 依赖关系
A类中某个方法的参数是用B类(接口)来声明的变量或某个方法返回的数据类型是B类型的,就是依赖关系。
UML图:虚线的起始端是A,终点端是B,终点端使用一个指向B的方向箭头表示虚线的结束。
4. 实现关系
一个类实现了一个接口,就是实现关系。
UML图:虚线的起始端是类,终点端是接口,终点端使用一个空心的三角形表示虚线的结束。
三、单件模式
1. 概念
单件类的构造方法访问权限是private.
单件类负责创建自己唯一的实例,并提供访问该实例的类方法.
2. 模式的结构与使用
- 构造方法私有化
- 本类内部创建对象实例
- 提供一个公有的静态方法,返回实例方法
3. 适用范围
当系统需要某个类只能有一个实例
4. 代码实例
//饿汉式:静态成员变量
public class Singleton {
//1.私有构造方法
private Singleton() {
}
//2.在本类中创建本类对象
private static Singleton instance = new Singleton();
//3.提供一个公共的访问方式,让外界获取该对象
public static Singleton getInstance() {
return instance;
}
}
public static void main(String[] args) {
//创建Singleton类的对象
Singleton instance = Singleton.getInstance();
Singleton instance1 = Singleton.getInstance();
//判断获取到的两个是否是同一个对象
System.out.println(instance == instance1);
}
//饿汉式:静态代码块方式
public class Singleton {
//1.私有构造方法
private Singleton() {
}
//2.声明Singleton类型的变量
private static Singleton instance;//值为null
//3.在静态代码块中进行赋值
static {
instance = new Singleton();
}
//4.对外提供一个获取该类对象的方法
public static Singleton getInstance() {
return instance;
}
}
public static void main(String[] args) {
Singleton instance = Singleton.getInstance();
Singleton instance1 = Singleton.getInstance();
//判断两次获取到的Singleton对象是否是同一个对象
System.out.println(instance == instance1);
}
//懒汉式
public class Singleton {
//1.私有构造方法
private Singleton() {
}
//2.声明Singleton类型的变量instance
private static Singleton instance; //只是声明了该类型的变量,并没有进行赋值
//3.对外提供访问方式
public static synchronized Singleton getInstance() {
//判断instance是否为null,如果为null,说明还没有创建Singleton类的对象
//如果没有,创建一个并返回,如果有,直接返回即可
if(instance == null) {
//线程1等待,线程2获取到cpu的执行权,也会进入到判断里面
instance = new Singleton();
}
return instance;
}
}
public static void main(String[] args) {
Singleton instance = Singleton.getInstance();
Singleton instance1 = Singleton.getInstance();
//判断两次获取到的Singleton对象是否是同一个对象
System.out.println(instance == instance1);
}
//懒汉式:静态内部类方式
public class Singleton {
//私有构造方法
private Singleton() {
}
//定义一个静态内部类
private static class SingletonHolder{
//在内部类中声明并初始化外部类的对象
private static final Singleton INSTANCE = new Singleton();
}
//提供公共访问方式
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Singleton instance = Singleton.getInstance();
Singleton instance1 = Singleton.getInstance();
System.out.println(instance == instance1);
}
四、工厂方法模式
1. 概念
工厂方法模式的关键是在一个接口或抽象类中定义一个抽象方法,该方法返回某个类的子类的实例,该抽象类或接口让其子类或实现该接口的类通过重写这个抽象方法返回某个子类的实例。
2. 模式的结构与使用
- 抽象产品:抽象类或接口,定义具体产品必须实现的方法
- 具体产品:类,实现抽象产品的方法
- 构造者:一个接口或抽象类,定义一个工厂方法(抽象),该方法返回具体产品类的实例
- 具体构造者:重写工厂方法,使该方法返回具体产品实例
3. 适用范围
- 用户需要一个类的子类的实例,但不希望与该类的子类形成耦合
- 用户需要一个类的子类的实例,但用户不知道该类有哪些子类可用
4. 代码实例
五、抽象工厂模式
1. 概念
抽象工厂模式的关键是在一个抽象类或接口中定义若干个抽象方法,这些抽象方法分别返回某个类的实例,该抽象类或接口让其子类或实现该接口的类重写这些抽象方法为用户提供一系列相关的对象。
抽象工厂可以生产多个等级的产品。
2. 模式的结构与使用
- 抽象产品:一个抽象类或接口,定义具体产品必须实现的方法
- 具体产品:类,实现抽象产品的方法
- 抽象工厂:一个接口或抽象类,定义若干抽象方法(就是创建产品的方法,例如Coffee createCoffee();)
- 具体工厂:具体工厂重写抽象工厂中的抽象方法,使该方法返回具体产品的实例
3. 适用范围
- 当需要创建的对象是一系列需要相互关联的产品族时,如电器工厂中的电视机、洗衣机等
- 系统中有多个产品族,但每次只使用其中的某一族产品,如有人只喜欢穿某一个品牌的衣服和鞋
六、原型模式
1. 概念
该模式的关键是将一个对象定义为原型,并为其提供复制自己的方法
2. 模式的结构与使用
- 抽象原型:一个接口,定义对象复制自身的方法
- 具体原型:实现接口,实现抽象原型中的方法
3. 适用范围
- 对象的创建非常复杂,可以使用原型模式
- 性能和安全要求比较高
七、生成器模式
1. 概念
将一个复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示
描述为主机与零件的关系
2. 模式的结构与使用
- 产品:定义变量,给变量创建set、get方法
- 抽象建造者:定义产品中变量的方法,例如:buildxxx();定义返回产品对象的方法,也就是返回值类型为产品。
- 具体建造者:实现抽象建造者中的方法
- 指挥者:先声明一个抽象建造者的变量,声明返回值类型为产品的组装方法
3. 适用范围
- 创建的对象较为复杂,由多个部件构成
- 对象的构建过程独立于创建该对象的类
八、代理模式
1. 概念
让用户通过访问代理来访问想要访问的对象
比如:秘书是老板的代理,老板和秘书都有听电话的方法:herePhone()。
代理模式最常见的两种情况:远程代理和虚拟代理
2. 模式的结构与使用
- 抽象主题:接口,通过接口或抽象类声明真实主题和代理对象的方法
- 实际主题:是实现抽象主题接口的类,是最终要引入的对象
- 代理:是实现抽象主题接口的类
3. 适用范围
- 不希望用户直接访问该对象,而是提供一个特殊的对象控制访问
- 需要很长的时间才能加载完成
- 对象位于远程主机上
九、适配器模式
1. 概念
将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
2. 模式的结构与使用
- 目标:目标是一个接口,该接口是客户想使用的接口。例:三头插座
- 被适配者:是一个已经存在的接口或抽象类,需要适配。例:两头插座
- 适配器:是一个类,实现了目标接口并包含有被适配者的引用。例:转换器
- 在主方法中,就用到了目标和适配器。
目标例如三头插座,被适配者例如手机充电器的二头插头,适配者是转换器
3. 适用范围
一个程序想使用已经存在的类,但该类所实现的接口和当前程序所使用的接口不一致
十、装饰模式
1. 概念
在不改变现有对象的情况下,动态地给对象添加一些额外的职责
2. 模式的结构与使用
- 抽象组件:是一个抽象类,准备接收附加责任的对象。例:写原有的行为。所有方法的声明都不是void
- 具体组件:是抽象组件的一个子类,实现抽象组件的抽象方法。例:具体写原有的行为
- 抽象装饰:是抽象组件的一个子类,包含抽象组件的实例,通过其子类拓展功能;包含声明抽象组件的变量。例:用构造方法保存引用
- 具体装饰:是抽象装饰的一个子类,实现的装饰的相关方法。例:写新的行为,并将原有的行为和新的行为组合在一起。
- 主方法:声明主方法,声明具体组件,声明具体装饰;还需定义一个方法,用来封装上面的组合方法;
3. 适用范围
程序希望动态的增强类的某个对象的功能,不影响到其他类的对象
十一、桥接模式
1. 概念
将抽象部分与它的实现部分分离,使他们都可以独立的变化,用组合关系代替继承关系
2. 模式的结构与使用
- 实现者:是一个接口,供细化对象角色调用
- 具体实现者:给实现者角色接口的具体实现
- 抽象:是一个抽象类,含有实现者声明的变量
- 细化抽象:是抽象角色的一个子类,委托所维护实现者类型对象调用相应的方法
3. 适用范围
存在两个独立变化的维度
4. 如何区分抽象和实现者
例如:
CCTV和节目,没有CCTV就看不了节目,所以CCTV是抽象,而节目是实现者
电脑系统和视频播放,没有电脑系统就看不了视频,所以电脑系统是抽象,而视频是实现者
十二、外观模式
1. 概念
为多个复杂的子系统提供一个一致的接口,而这些子系统更加容易访问
2. 模式的结构与使用
- 子系统:是一个类,实现系统部分功能
- 外观:是一个类,为多个子系统对外提供一个共同的接口,子系统在外观类中需进行声明变量。
- 分析问题:例如进行邮寄,有三个步骤,分别是检查安全性、按照重量计算邮费和选择邮递方式。在这三个子系统都需要写有参构造方法,在外观类中三个子系统都需要声明,且在三个子系统中写的变量也要在外观类中声明。
3. 适用范围
对于一个复杂的子系统,需要为用户提供一个简单的交互操作
十三、组合模式
1. 概念
将对象组合成树形结构以表示“部分-整体”的层次结构。例如:系统文件
2. 模式的结构与使用
- 抽象组件:是一个接口(抽象类),定义系统各层次对象的共有方法和属性,预先定义一些行为和属性
- 树枝节点:实现抽象组件的实例
- 叶子节点:实现抽象组件的实例
3. 适用范围
- 当想表示对象的部分-整体层次结构
- 希望用户用一致的方式处理个体对象和组合对象
十四、享元模式
1. 概念
通过共享已经存在的对象来减少需要创建的对象数量,关键是使用一个称作享元的对象为其他对象提供共享的状态,而且能够保证使用享元的对象不能更改享元中的数据。
2. 模式的结构与使用
- 享元接口:是一个接口,定义了享元对外公开其内部数据的方法,以及享元接收外部数据的方法
- 具体享元:实现享元接口的类
- 享元工厂:是一个类,该类的实例负责创建和管理享元对象
案例为俄罗斯方块
3. 适用范围
一个应用程序使用大量的对象,这些对象之间部分属性本质上是相同的,用享元来封装相同的部分
十五、模板方法模式
1. 概念
模板模式使子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤
例如:
去银行:取号、排队、办理业务、评分
取号、排队、评分在父类中实现
办理业务在子类中实现
2. 模式的结构与使用
- 抽象模板:是一个抽象类。包含基本方法和模板方法。基本方法中有抽象方法、具体方法和钩子方法;模板方法负责调用。
- 具体模板:是抽象模板的子类。
3. 适用范围
设计者需要给出一个算法的固定步骤,并将某些步骤的具体实现留给子类来实现
十六、策略模式
1. 概念
定义一系列算法,把它们一个一个封装起来,并且使它们可相互替换
2. 模式的结构与使用
- 抽象策略:接口,定义了若干个抽象方法
- 具体策略:实现抽象策略接口所定义的抽象方法,即给出算法标识的具体算法
- 上下文:包含有策略声明的变量
案例:不同的节日超市有不同的优惠活动,通过促销员来介绍活动
在抽象策略中写抽象方法;在具体策略中实现抽象策略的方法;在上下文中首先声明抽象策略的变量,其次写有参构造方法,参数为声明的抽象策略,然后在方法中调用声明的变量进行“点”。
3. 适用范围
使用一个算法的不同变体
十七、命令模式
1. 概念
将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开
2. 模式的结构与使用
- 命令接口:是一个接口,用来封装“请求”的若干个方法
- 具体命令:具体命令是实现命令接口的类的实例,实现命令接口中的方法
- 请求者:包含Command接口变量的类的实例
- 接收者:是一个类的实例
案例:在饭店里点餐,有订单、服务员、厨师。
1. 命令接口中有一个方法void execute(); //执行命令;
2. 具体命令中实现命令接口,重写其中的方法,含有接收者的引用,并在有参构造方法中引用接收者的引用;
为什么含有接收者的引用?是因为具体命令是由接收者知道的
具体命令中需要实现抽象命令的方法,在重写的方法中需要调用接收者的行为,所以要在具体方法中声明并调用
3. 请求者中包含命令接口的变量实例;
4. 接收者写自己的方法
3. 适用范围
需要在不同的时刻指定、排列和执行请求
十八、责任链模式
1. 概念
使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。
2. 模式的结构与使用
- 抽象处理者:接口,包含抽象处理方法和后继连接
- 具体处理者:具体处理者是实现处理者接口的类的实例
3. 适用范围
有许多对象可以处理用户的请求
十九、状态模式
1. 概念
允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类
2. 模式的结构与使用
- 环境:是一个类,该类含有抽象状态声明的变量,可以引用任何具体状态类的实例
- 抽象状态:抽象状态是一个接口或抽象类
- 具体状态:是实现抽象状态的类
3. 适用范围
一个对象的行为依赖它的状态,并且它必须在运行时根据状态改变它的行为
二十、观察者模式
1. 概念
定义对象间的一对多的依赖关系。
2. 模式的结构与使用
例如:招聘大厅中的关系;
- 抽象主题:接口,写添加、删除、通知观察者的方法,需要依赖观察者。例:像招聘大厅中的前台,负责接收信息。
- 具体主题:类,写arrayList来接收观察者,实现抽象主题的方法。例:像招聘大厅的后台,处理信息。
- 观察者:接口,写更新方法。
- 具体观察者:类,需要关联抽象主题。
- 主方法:声明具体主题,调用添加方法、更新方法。