一、七大原则
1.单一职责原则
一个类只负责一项职责(并不是一个类只有一个方法)
2.接口隔离原则
客户端不依赖不需要的接口
改进后:
3.依赖倒转原则
- 高层模块不依赖底层模块,都应该依赖抽象(接口或抽象类)
- 抽象不依赖细节,细节(实现类)依赖抽象
- 依赖倒转的核心是面向接口编程
依赖关系传递的三种方式:接口传递、构造方法传递、setter方式传递
4.里氏替换原则
继承时,子类中尽量不要重写父类的方法
5.开闭原则【OCP】
对扩展开放,对修改关闭
6.迪米特法则
迪米特法则又叫最少知道原则,一个对象应该对其他对象保持最少的了解。
这里面的输出员工信息,放在自己的类里面对外提供public方法,不在另一个类重复这段代码,只需要调用该方法,即符合迪米特法则。
7.合成复用原则
尽量使用合成/聚合的方式,而不是使用继承
聚合:
合成:
设计原则核心:
- 找出应用中可能需要变化的,独立出来,不要和不需要变化的代码混在一起
- 针对接口编程,不针对实现编程
- 松耦合
二、UML类图
三、设计模式(23种)
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
amazing...
1 单例模式
1.1 饿汉式(静态常量)
//构造器私有化
//静态常量本类对象
//对外提供getInstance方法
public class Singleton{
private Singleton(){ }
private static final Singleton instance = new Singgleton();
public static Singleton getInstance(){
return instance; } }
advantage:
- 写法简单
- 类装载时完成了实例化,避免了线程同步的问题
disadvantage:
- 类装载时就实例化,没有达到懒加载的效果
- 如果不用这个实例,会造成内存浪费
1.2 懒汉式
1.2.1 线程不安全
public class Singleton{
private Singleton(){ }
private static Singleton instance;
public static Singleton getInstance(){
if(instance == null){ instance = new Singleton(); } return instance; } }
advantage:
- 达到了懒加载的效果
disadvantage:
- 线程不安全,多个线程同时进会创建多个实例
1.2.2 线程安全
public class Singleton{
private Singleton(){ }
private static Singleton instance;
public static synchronized Singleton getInstance(){
if(instance == null){ instance = new Singleton(); } return instance; } }
advantage:
- 解决了线程不安全问题
disadvantage:
- 效率太低
1.2.3 DoubleCheck
public class Singleton{
private Singleton(){ }
private static volatile Singleton instance;
public static Singleton getInstance(){
if(instance == null){ synchronized(Singleton.class){ if(instance == null){ instance = new Singleton(); } }
} return instance; } }
advantage:
- 解决了线程不安全问题
- 实现懒加载
1.2.4 静态内部类
public class Singleton{
private Singleton(){ }
private static class SingletonInstance{
private static final Singleton INSTANCE = new Singleleton(); }
public static Singleton getInstance{
return SingletonInstace.INSTANCE; } }
1.2.5 枚举
enum Singleton {
INSTANCE;}
2 原型模式
克隆羊:传统模式
优点
- 好理解,简单易操作
缺点
- 创建新的对象时,需要重新获取原始对象的属性,创建的对象比较复杂时,效率较低
- 不能动态获得对象运行时的状态,不够灵活
优点
- 不用重新初始化对象,动态获得对象运行时的状态
- 原始对象发生改变时,不需要修改源码,克隆对象也会改变。
缺点
- 需要为类配置一个深克隆方法,对新类来说不是很难,但是对已有的类进行改造时,需要修改源码,违背了 OCP 原则
3 工厂模式
3.1.1 简单工厂(不算一种设计模式)
传统模式
传统方式新增 pizza 种类时,调用者的代码需要做大量的修改,违反了 OCP 原则。
简单工厂模式
工厂创建具体的 pizza ,调用者找 工厂就ok了。
//日历对象的创建,就使用到了简单工厂模式
Calendar.getInstance();
3.1.2 工厂方法模式
对象的实例化推迟到子类
3.2.3 抽象工厂模式
4 建造者模式
【也称为生成器模式】
盖房子:传统方式
优点
- 好理解,简单易操作
缺点
- 程序结构过于简单,没有设计缓存层对象,可扩展性和可维护性不好
解决方案
把产品和产品建造过程解耦 ==> 建造者模式
盖房子:建造者
//StringBuilder 就用到了建造者模式
StringBuilder
注意事项:
- 客户端不必知道产品内部的组成细节,将产品与产品的创建解耦,使相同的创建过程可以创建不同的产品
- 指挥者可以控制产品的创建过程
- 新增具体建造者不需要修改源码,指挥者也可不用修改,直接在客户端调用,符合开闭原则
5 适配器模式
5.1 类适配器
基本介绍:Adapter 类通过继承 src 类,实现 dst 接口,完成 src-->dst 的适配
注意事项:
- 类适配器继承了 src 类,有了一定的局限性(java是单继承)。
- src 类的方法会暴露在 Adapter ,增加了使用成本
- 可以重写 src 类的方法,所以会更灵活
5.2 对象适配器(常用)
对象适配器和类适配器模式相同,只是 Adapter 不再继承 src 类,而是持有 src 类。
根据合成复用原则,尽量用关联关系代替继承。
5.3 接口适配器
接口中定义一堆方法,使用一个抽象类实现接口,并为该接口中的每一个方法提供一个默认的实现(空方法),那么该抽象类的子类可以有选择地覆盖父类的某些方法。
6 桥接模式
- 新增一个样式,每个牌子的手机都要增加一个;新增一个手机,会在三个样式下都增加一个手机。增加了代码的维护成本。
- 违反了单一职责原则。
- 解决方案:桥接模式
桥接模式:结构型,基于类的最小设计原则。将抽象和实现分开,两个层次可以独立改变。
桥接模式解决手机问题:
桥为抽象类 Phone。
7 装饰者模式
符合 OCP 原则。
动态的将新功能附加到对象上,功能扩展更灵活。
8 组合模式
注意事项
- 简化客户端操作
- 具有较强的扩展性
- 方便创建出复杂的层次结构
- 需要遍历组织机构的,强烈推荐使用组合模式
- 但是,要求较高的抽象性,如果节点和叶子节点有很多差异,则不适用组合模式
HashMap 中使用到了组合模式,component 为 AbstractMap。
9 外观模式
外观模式也叫 “过程模式” ,提供一个高层接口,调用端只需要跟这个接口发生调用。
注意事项
- 系统需要分层设计可以使用外观模式。
- 屏蔽了子系统的细节。解决多个复杂接口带来的调用困难,简化操作。
- 合理使用外观模式,直接调用模块很方便时就不要使用外观模式。
MyBatis 中的 Configuration 创建 MetaObject 使用了外观模式。
10 享元模式
享元模式:运用共享技术有效地支持大力度的对象。
能解决重复创建对象的内存浪费问题。Eg,String常量池、数据库连接池。
Integer类中就使用到了享元模式, -128 ~ 127 共享缓存池中的对象,范围外的就不在缓存池了,而是创建新的对象。所以 Integer.valueOf(127) == Integer.valueOf(127) 为 true。
11 代理模式
好处:对目标对象的方法增强,即扩展目标对象的功能。
目标对象可以是:远程对象,创建开销大的对象,需要安全控制的对象。
三种代理形式:静态代理,JDK 动态代理,cglib 代理。
12 模板方法模式
制作豆浆
注意事项和细节:
基本思想:算法只存在一个地方(父类中),易修改。
实现了最大代码复用。
模板方法都要加上final关键字,防止子类修改模板方法。
适用场景:当要完成某个过程,该过程要执行一系列步骤,这一系列步骤基本相同,个别步骤在实现时可能不同。
缺点:每一个不同的实现都需要一个子类实现,导致类的个数增加,使系统更加庞大。
13 命令模式
命令模式,将发起请求、执行请求的对象解耦。
缺点:可能导致某些系统有过多的具体命名类,增加系统的复杂度。
14 访问者模式
访问者模式
访问者模式解决测评系统:
符合单一职责原则,扩展性、灵活性更好。
缺点:违反了依赖倒转原则。访问者依赖的是具体的元素,而不是抽象元素。对访问者公布细节。
15 迭代器模式
优点:
1.提供了一个统一的方法遍历对象,用户不用考虑聚合类型,使用一种方法就可以遍历对象;
2.符合单一职责原则,一个类只有一个引起变化的原因。
3.隐藏聚合的内部结构,客户端要遍历集合的时候只能取到迭代器,而不会知道聚合的具体构成。
缺点:
每个聚合对象都要一个迭代器,会产生多个迭代器不好管理类。
16 观察者模式
需求:天气预报
观察者模式解决天气预报
17 中介者模式
中介者模式,用一个中介对象来封装一系列的对象交互。
中介者模式解决智能家庭管理
18 备忘录模式
19 解释器模式
四则运算问题
20 状态模式
APP抽奖活动
21 策略模式
鸭子问题——传统解决方案
带来的问题
鸭子问题——策略模式解决方案
策略模式,定义算法族,封装起来可以相互替换。
鸭子问题具体的策略:
22 责任链模式
需求
springMVC的拦截器使用到了责任链模式
注意事项和细节:
- 请求和处理分开,实现解耦,提高系统的灵活性
- 简化对象,使对象不需要知道链的结构
- 链特别长的时候,性能会受到影响,因此需要控制链的节点数
- 调试不方便,采用了类似递归的方式
- 适用场景:多个对象处理同一个请求,比如:多级请求,请求/加薪等审批流程、Java web中Tomcat对Encoding的处理、拦截器。