设计模式
什么是设计模式
- 设计模式是一种代码规范,是经过了很久的验证后总结出来的一种模式,它可以解决我们开发中常见的问题,还可以实现重用代码,开发起来更加灵活,保证了代码可靠性可维护性,让代码更容易被理解。我们可以想象一下拼积木的时候某些结构
不适合某些形状的积木,或者某些结构需要反复使用,那我们搭的久了就会有一些经验,知道用什么方式去组合积木来搭建哪些复杂的地方,满足特殊的需求,就像我们写代码一样,需要创建多个相似的对象时,就可以通过设计模式来封装对象的创建过程,实现重用代码
设计模式的六大原则
1. 单一原则:一个类或者一个方法负责一项原则(复用性提高)
2. 里氏替换原则:子类可以扩展父类的功能,但不改变原有父类的功能
3. 依赖倒置原则:面向接口编程(通过接口参数作为参数实现应用场景),变量或者参数传递,应该尽量使用抽象类,或者接口
4. 接口隔离:建立单一接口,复杂的接口应该拆分成多个简单接口,将接口拆分成更小的、更具体的部分,以确保客户端只需要依赖它们需要的接口
5. 迪米特原则:最少知道原则,降低类与类之间的耦合,一个对象应该与其它对象保持最少的了解,一个对象避免和陌生对象通信,降低对象之间的耦合度。
6. 开闭原则:软件实体(类、模块、函数等)应该对扩展开放,对修改闭合。通过使用接口、抽象类或者基类来编程,能够方便地添加新的功能,而不需要修改现有代码。
介绍一下单例模式:
单例模式的定义就是保证一个类只有一个实例,并提供全局访问点,其中单例模式又分为懒汉式和饿汉式,我们一起来看一下
- 饿汉式:
public class Singleton {
private static Singleton INSTANCE = new Singleton();
private Singleton() {
// 私有构造函数,避免外部创建对象
}
public static Singleton getInstance(){
return INSTANCE;
}
}
饿汉式的单例模式在类加载的时候就会创建好实例,因此不存在线程安全问题,但是可能会浪费一些内存资源
- 懒汉式
public class Singleton {
private static Singleton INSTANCE = null;
private Singleton() {
// 私有构造函数,避免外部创建对象
}
public static synchronized Singleton getInstance(){
if (INSTANCE == null){//为空了再new,不为空则不new
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
懒汉式的单例模式是指在第一次使用时才会创建实例,可以延迟实例化的时机,避免了饿汉式的资源浪费问题。在该实现中,静态变量instance不会在类加载时就初始化,而是在第一次调用getInstance()方法时进行实例化。需要注意的是这种方式在多线程环境下可能会引发线程安全问题,因此在高并发场景下,可以考虑使用双重检查锁
- DCL单例
public class Singleton {
private volatile static Singleton INSTANCE;
private Singleton() {
// 私有构造函数,避免外部创建对象
}
public static Singleton getInstance(){
if (INSTANCE==null)
synchronized (Singleton.class){
if (INSTANCE==null){
INSTANCE = new Singleton();
}
}
return INSTANCE;
}
}
DCL懒汉式单例模式是指在多线程环境下,先进行一次空判断来避免非必要的同步,再在同步块中进行实例化操作,在上面代码中,静态变量instance使用了volatile关键字来确保其可见性和禁止指令重排序,当instance为null时,进入同步代码块,再次判断instance是否为null,如果是,则进行实例化并赋值给instance变量。使用DCL方式保证了多线程情况下的线程安全
- 静态内部类
public class Singleton {
private Singleton() {
// 私有构造函数,避免外部创建对象
}
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
我们可以看到私有的构造函数和静态内部类SingletonHolder确保了外部无法直接创建Singleton类的对象,并且只有在调用getInstance()方法时才会进行实例化。SingletonHolder中的静态变量INSTANCE会在第一次使用时进行初始化,由于类加载机制的特性,保证了线程安全。这种方式延迟了实例化的时机,同时又保证了性能和线程安全。
Builder建造者模式
- 建造者模式由两个主要角色组成:建造者和指挥者,建造者就是造房子的人,由他负责定义构建对象的各个步骤,并提供相应的方法,指挥者则是我,房子是我的,我想怎么建就告诉建造者,协调建造者的工作流程,确保按照正确的顺序进行建造,通过使用建造者模式可以将复杂对象的构建过程与表示分离在不同的方法中,使得创建过程更加清晰,并且每个具体建造者都是相互独立的,因此可以方便的替换具体建造者或增加新的具体建造者,用户使用不同的具体建造者即可得到不同的产品对象。
静态代理与动态代理
代理,字面意思很好理解,就像一个中间人代替我去处理某些事情,比如排队,买票。而在开发中也差不多,它可以充当一个中间层,将客户端和具体的对象之间进行隔开,通过代理对象来访问真实对象,通过建立一个对象代理类,由代理对象控制原对象的引用,从而实现对真实对象的操作。
-
静态代理就像是你提前请了一个替身,在编译代码的时候就确定了这个关系。程序员需要亲自创建一个代理对象,这个对象同时持有了原始对象的引用,并且实现了原始对象相同的接口。当客户端调用代理对象的方法时,代理对象会在方法执行前后加入一些额外的操作,比如记录日志、权限控制等。这样做的好处是代理关系在编译时就确定了,让人一目了然。
-
动态代理就像是你临时找了一个替身,不需要提前创建代理对象。运行代码时,框架会在运行时生成代理对象,省去了手写代码的麻烦。通过动态代理,我们可以根据需要动态地添加、修改或删除一些额外的操作,这让代理关系更加灵活可扩展,同时也减少了对原始对象的侵入。
观察者模式
- 观察者模式定义了对象间的一种一或一对多的依赖关系,当一个对象的状态发生变化时,跟它依赖的对象都会收到通知并自动被更新,在这个模式里面有两种角色,一个是被观察者,一个是观察者,当被观察者发生变化时会通知到所有的观察者,观察者观察到发生的变化之后就会进行更新
工厂模式
- 工厂模式的核心思想就是将对象的创建过程进行封装,对外提供一个统一的接口来创建对象,而不需要了解具体的创建细节,想象一下我们在一家餐馆点菜。我不用去厨房亲自炒菜,而是告诉服务员我要吃什么,然后等他们为我送过来。在这个例子中,我就是客户端,餐馆就是工厂,而菜品就是工厂生产的产品。在工厂模式中就有这3个角色:
1. 产品:表示我们需要的对象,比如菜品
2. 工厂:负责创建产品的类,比如餐馆,会根据客人的需求制作不同的菜品
3. 客户端:向工厂提出需要什么产品,并接收工厂创建的产品,就像我们点餐一样
工厂模式的目的是为了让我们创建对象更加方便和灵活,客户端只需要告诉工厂需要什么产品,而工厂会根据需求来创建相应的产品,客户端不需要知道具体的创建过程,只需关心所需要的产品即可。这样,当我们需要修改或添加新的产品时,只需要修改工厂类就行,不用在客户端的代码中进行修改,提高了代码的可维护性和扩展性。
责任链模式
- 责任链模式是一种请求处理的模式,可以将请求的处理者组织成一条链,沿着链去传递,直到某个处理者能处理这个请求,否则将一直传递,就比较像我们生活中碰到问题,我先找到第一个人如果它处理不了,那我就接着找第二个,第二个也不行那就接着找第三个,以此类推,直到找到能处理问题的