写在前面
发现对于落地这件事情还是要静下心一个一个目标完成,设计模式一直搁浅了好久也没个系统整理,作为网上标配开篇,最近还是补上这个作业吧
为什么用设计模式
- 设计模式是前人总结下来的经验,对于扩展性和可维护性有很大帮助
- 也是为了使设计变得简单,容易阅读
设计模式原则(SOLID)
- 单一职责原则(Single Responsibility Principle):可以理解为最好一个类只负责一项职责
- 开闭原则(Open Close Priciple):尽量对扩展开放,对修改关闭
- 里氏替换原则(Liskov Substitution Principle):引用父类处可以用任意子类代替
- 接口隔离原则(Interface Segregation priciple):建立单一接口,最好是一个类依赖一个接口,而不是多个类依赖一个接口
- 依赖倒置原则 (Dependency InVersion Principle) :调用方和实现方都应该依赖抽象,彼此相互独立,实现类应该依赖抽象,而不能反过来
- 迪米特法则(Law of Demeter):一个对象保持对其他对象最少的了解
- 合成复用原则(Composite/Aggregate Reuse Principle):尽量使用组合/聚合,不要使用继承,继承基类会暴露实现破坏封装;基类改变,子类实现也需要改变;实现是静态的,不够灵活
如何使用设计模式
以上原则只是设计参考的一个约束,并不绝对,对于“最好的设计模式就是不用设计模式”,我们还没有达到这个境界,只有合适的场景用更合适的方法。
设计模式-创建型
目的:实例化过程的解耦
我们原先想获取一个新对象
1 | Object o = new Object(); |
之后在创建新对象的场景可以参考考虑一下使用以下的思路
单例模式
说明:一个类只能有一个实例,提供全局唯一的访问点
匿名内部类
1
2
3
4
5
6
7
8
9
10
11
12
13class SingletonInnerClass {
// 私有构造器保证不能new 创建新实例
private SingletonInnerClass() {
}
public static SingletonInnerClass getInstance() {
return SingletonInner.instance;
}
private static class SingletonInner {
private static final SingletonInnerClass instance = new SingletonInnerClass();
}
}枚举类型
1
2
3enum SingletonEnum {
INSTACN;
}双重检查锁
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18class SingletonDCL {
private volatile static SingletonDCL instance;
private SingletonDCL() {
}
public static SingletonDCL getInstance() {
if (instance == null) {
synchronized (SingletonDCL.class) {
if (instance == null) {
instance = new SingletonDCL();
}
}
}
return instance;
}
}Spring单例注册表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33/** Cache of singleton objects: bean name to bean instance. */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** Cache of singleton factories: bean name to ObjectFactory. */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/** Cache of early singleton objects: bean name to bean instance.
提前曝光的单例Cache
*/
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 一级缓存 获取单例的bean
Object singletonObject = this.singletonObjects.get(beanName);
// 判断bean是否在创建中(并未创建完)
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
// 二级缓存 获取提前曝光的单例
singletonObject = this.earlySingletonObjects.get(beanName);
// 判断是否允许提前引用
if (singletonObject == null && allowEarlyReference) {
// 三级缓存 获取单例bean
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 放入二级缓存 并删除三级缓存中的bean
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}上面也直接说了spring 对于循环依赖的解决方案
简单工厂
说明:根据传入的变量决定输出什么样的实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30interface Product {
void use();
}
// 产品实现
class ProductA implements Product {
public void use() {
System.out.println("product A");
}
}
class ProductB implements Product {
public void use() {
System.out.println("product B");
}
}
// 工厂
class Factory {
public Product produce(String type) {
if ("A".equals(type)) {
return new ProductA();
} else if ("B".equals(type)) {
return new ProductB();
} else {
return null;
}
}
}
工厂方法
说明:创建对象行为进行抽象,在子类里实现逻辑
适用场景:
如下是spring中的工厂方法接口
1
2
3
4
5
6
7
8
9
10
11public interface FactoryBean<T> {
T getObject() throws Exception;
Class<?> getObjectType();
default boolean isSingleton() {
return true;
}
}jdk中Collection类
1
2
3
4
5
6
7
8
9
10
11
12public interface Collection<E> extends Iterable<E> {
...
// 这是一个工厂方法
Iterator<E> iterator();
...
}
// 实现在子类中
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
public Iterator<E> iterator() {
return new Itr();
}
}
抽象工厂
说明:创建相关或依赖对象的家族,而无需明确指定具体类
- Collection类中抽象了多个工厂方法,本身又是一个抽象的创建类
建造者模式
说明:封装一个对象复杂的构建过程
lombok @Builder
1
2
3
4Builder builder = Builder
.age(10)
.name("builder")
.build();
原型模式
说明:实例对象的复制获取新实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18/**
* 浅拷贝
* 对象内的引用也被复制时为深拷贝
*/
class Prototype implements Cloneable {
private String name;
private Map<String, String> map;
public Prototype clone() throws CloneNotSupportedException {
Prototype prototype = (Prototype) super.clone();
prototype.map = map;
prototype.name = name;
return prototype;
}
}总结
以上是对创建型的设计模式的一些demo及一些源码的引用,目的是尽快的理解和快速的用起来,后续会补全UML图
其中最常用的是单例模式/工厂方法/抽象工厂/建造者模式,设计模式的主要目的也是为了代码的可维护性和可扩展性,把会变动的地方和不变的地方隔离开来
如有不正确的地方欢迎大佬指正