1、设计模式概念
设计模式:是系统服务设计中针对场景的一种解决方案,可以解决功能逻辑开发中的共性问题。
2、六大设计原则
单一职责原则 (单一功能原则)
原则定义:一个类应该只有一个发生变化的原因。
开闭原则
定义:扩展开放,修改封闭。
对于不应该修改的方法修饰为private 不允许修改。或者可以扩展不允许修改当前方法代码。
里氏替换原则 ->继承类的原则
定义:继承必须确保超类所拥有的性质在子类中依然成立。
也就是说:子类与父类有相同的功能。
案例
迪米特法则原则
最少知道、减少依赖、减低耦合
接口隔离原则
将臃肿庞大的接口拆分为更小的和更具体的接口,让接口只包含客户感兴趣的方法。->更小,更具体的接口
依赖倒置
接口 和 具体实现类,调用时不会关注具体类怎么实现的。
3、设计模式如何落地
4、工厂方法模式
⼯⼚模式⼜称⼯⼚⽅法模式,是⼀种创建型设计模式,其在⽗类中提供⼀个创建对象的⽅法, 允许⼦类 决定实例化对象的类型
5、抽象工厂模式
5.1 工厂模式分类对比介绍
5.2 抽象工厂案例
6、建造者模式
6.1 王者荣耀地图建造师
元素重复使用
6.2 建造者模式案例
指将一个复杂的对象的构造与它的表示分离,使同样的构造过程可以创建不同的表示。它是将一个复杂的对象分解成多个简单的对象,然后一步步构建而成。
7 原型模式
8 单例模式
8.2 单例模式原则
1、私有构造。(阻止类被通过常规方法实例化)
2、以静态方法或枚举返回实例。(保证实例的唯一性)
3、确保实例只有一个,尤其是多线程环境。(保证在创建实例时的线程安全)
4、确保反序列化时不会重新构建对象。(在有序列化反序列化场景下防止单例被莫名破坏,造成未考虑到的后果)
手段
主动处理:synchronized、volatile 、cas
JVM机制:
1、由静态初始化器(在静态字段上或statics{}块中的初始化器)初始化数据时
2、访问final字段时
3、在创建线程之前创建对象时
4、线程可以看见它将要处理的对象时
8.3 创建类型
饿汉模式、懒汉模式双重锁懒汉模式、静态内部类模式、枚举模式
8.3.1 饿汉模式(线程安全)
package cn.bugstack.design;
public class Singleton_03 {
private static Singleton_03 instance = new Singleton_03();
private Singleton_03() {
}
public static Singleton_03 getInstance() {
return instance;
}
}
8.3.2 懒汉模式
# 线程不安全
package cn.bugstack.design;
public class Singleton_01 {
private static Singleton_01 instance;
private Singleton_01() {
}
public static Singleton_01 getInstance(){
if (null != instance) return instance;
instance = new Singleton_01();
return instance;
}
}
8.3.3 懒汉模式 (线程安全模式)
package cn.bugstack.design;
public class Singleton_02 {
private static Singleton_02 instance;
private Singleton_02() {
}
public static synchronized Singleton_02 getInstance(){
if (null != instance) return instance;
instance = new Singleton_01();
return instance;
}
}
可以进一步优化,锁粒度更细。
8.3. 4 饿汉模式 双重检验加锁
package cn.bugstack.design;
public class Singleton_05 {
private static volatile Singleton_05 instance;
private Singleton_05() {
}
public static Singleton_05 getInstance(){
if(null != instance) return instance;
synchronized (Singleton_05.class){
if (null == instance){
instance = new Singleton_05();
}
}
return instance;
}
}
8.3.5 类的内部类(线程安全)
延迟加载。
JVM机制,只有一个类被执行,其它类会被阻塞。
package cn.bugstack.design;
public class Singleton_04 {
private static class SingletonHolder {
private static Singleton_04 instance = new Singleton_04();
}
private Singleton_04() {
}
public static Singleton_04 getInstance() {
return SingletonHolder.instance;
}
}
8.3.6 CAS
package cn.bugstack.design;
import java.util.concurrent.atomic.AtomicReference;
public class Singleton_06 {
private static final AtomicReference<Singleton_06> INSTANCE = new AtomicReference<Singleton_06>();
private static Singleton_06 instance;
private Singleton_06() {
}
public static final Singleton_06 getInstance() {
for (; ; ) {
Singleton_06 instance = INSTANCE.get();
if (null != instance) return instance;
INSTANCE.compareAndSet(null, new Singleton_06());
return INSTANCE.get();
}
}
}
8.3.7 枚举单例
package cn.bugstack.design;
public enum Singleton_07 {
INSTANCE;
public void test(){
System.out.println("hi~");
}
}
结构型模式(7节)
这类模式介绍如何将对象和类组装成较⼤的结构, 并同时保持结构的灵活和⾼效。 结构型模式包括:适配器、桥接、组合、装饰器、外观、享元、代理,这7类
9 适配器模式
生活中的场景:变速箱换挡
10 桥接模式
生活案例:植物嫁接、秃头植发。
在支付中有多种认证模式(指纹、人脸等),将多认证模式桥接到支付系统中。
11 组合模式
需要用到决策树,会比较复杂一点去实现。
子节点是具体的决策,执行的业务。 其它节点是一些决策信息。
12 装饰器模式
生活场景:装饰QQ秀、
在不改变现有的对象结构情况下,动态地给对象增加一些职责(即增加额外功能)的模式。
模拟单点登录服务
13 外观模式
隐藏系统的复杂性,并向客户端提供了一个客户端可以访问的系统的接口。这种类型的设计模式属于结构模式,它向现有的系统添加一个接口来隐藏系统的复杂性。
场景使用AOP,接口白名单,插拔式,配置式白名单
迪米特法则:降低耦合,减少依赖
14 享元模式 一个思想
主要减少创建对象的数量,以减少内存占用和提高性能。
spring IOC 共享对象
15 代理模式
一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。在代理模式中,我们创建具有现有对象,以便向外界提供功能接口。
16 责任链模式
为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,知道有对象处理它为止。
流程审批例子
17 命令模式
将一个请求封装为一个对象,使发 出请求的责任和执行请求过程分割开。这样两者之间通过命令对象进行沟通,便于命令对象进行存储、传递、调用、增加与管理。
18 迭代器模式
生活场景:军训报数
提供一个方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示。
Java:HashMap 顺序遍历、List顺序遍历
19 中介者模式
定义一个中介对象来封装一系列对象之间的交互,使原有对象之间的耦合松散,且可以独立地改变它们之间的交互。又称调停模式,她是迪米特法则的典型应用。(最少知道,减少依赖)
20 备忘录模式
生活场景:日记、PhotoShop历史记录
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之前保存这个状态,以便以后当需要时能将该对象恢复到原先保存的状态。
21 观察者模式
指多个对象间存在一对多的依赖关系,当一个对象的状态发生变化改变时,所有依赖于它的对象都得到通知并自动更新。又称发布-订阅模式、模型-视图模式,他是对象行为模式。
22 状态模式
将有状态的对象,把复杂的“判断逻辑”提取到不同的状态对象中,允许状态对象在其内部状态发生时改变其行为。
23 策略模式
定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。 策略模式属于行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对象这些算法进行管理
出行样例:
24 模板模式-行为型模式
定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。
spring抽象工厂、抽象bean创建类
25 访问者模式
将作用域某种结构中的各元素的操作分离出来封装成独立的类,使其在不改变数据结构的前提下可以增加作用于这些元素新的操作,为数据结构中的每个元素提供多种访问方式。
文件遍历的案例:
package com.momoc.study.netty;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.concurrent.atomic.AtomicInteger;
public class TestFilesWalkFileTree {
public static void main(String[] args) throws IOException {
//访问者模式
AtomicInteger dirCount = new AtomicInteger();
AtomicInteger fileCount = new AtomicInteger();
final Path path = Files.walkFileTree(Paths.get("/Library/Java/JavaVirtualMachines/jdk1.8.0_271.jdk"), new SimpleFileVisitor<Path>(){
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
System.out.println("===>" + dir);
dirCount.incrementAndGet();
return super.preVisitDirectory(dir, attrs);
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
fileCount.incrementAndGet();
System.out.println(file);
return super.visitFile(file, attrs);
}
});
System.out.println("FileCount:" + fileCount + " DirCount:" + dirCount);
}
}