设计模式之单例模式和工厂模式(代码+举例)

文章目录

  • 开闭原则
  • 工厂模式
    • [1. 简单工厂模式(耦合度低)](#1. 简单工厂模式(耦合度低))
    • [2. 静态工厂模式(同上)](#2. 静态工厂模式(同上))
    • [3. 工厂方法(无耦合)](#3. 工厂方法(无耦合))
    • [4. 抽象工厂模式](#4. 抽象工厂模式)
  • 单例模式
    • [1. 饿汉式](#1. 饿汉式)
    • [2. 懒汉式](#2. 懒汉式)
      • [1.1 线程不安全](#1.1 线程不安全)
      • [1.2 Double Check 线程安全方式](#1.2 Double Check 线程安全方式)

前言:如果你学过springboot,并知道自动配置,但你不知懂工厂模式,单例模式等,那么你是纯纯的八股小子(跟我一样),有点水平的面试官如果问了这两个问题你只会自动配置不会工厂模式,你大概率会被pass,学完设计模式,你就可以吊打面试官了
本文以 举例+代码 的方式,循序渐进的讲解设计模式

开闭原则

  • 对扩展开放,对修改关闭,尊虚开闭原则可以达到解耦的效果

工厂模式

  • 工厂说白了就是创建对象的,我创建对象不需要在业务层new了,直接调用工厂的方法获取对象
  • **解耦:**当我们想要添加新的实体类时,不需要改动工厂类和业务类,只添加实体类即可,这就是扩展了功能但没有修改源代码,因为你只是增加了一个新的类而已

1. 简单工厂模式(耦合度低)

顾客点咖啡案例 - 可以先看总结

工厂代码:

java 复制代码
public class CoffeeFactory {
    public Coffee createCoffee(String type){
        Coffee coffee = null;
        if ("American".equals(type)){
            coffee = new AmericanCoffee();
        } else if ("latter".equals(type)){
            coffee = new LatterCoffee();
        }
        return coffee;
    }
}

业务层代码:

java 复制代码
public class CoffeeStore {
    public Coffee orderCoffer(String type){
        CoffeeFactory coffeeFactory = new CoffeeFactory();
        Coffee coffee = coffeeFactory.createCoffee("latter");
        coffee.make();
        return coffee;
    }
}

顾客代码:

java 复制代码
public class Customer {
    public static void main(String[] args) {
        CoffeeStore coffeeStore = new CoffeeStore();
        Coffee coffee = coffeeStore.orderCoffer("latter");
    }
}

**总结:**可以看到业务层解耦了,不用new对象了,但是工厂还是有耦合,如果我想增加橙C美式咖啡,还是需要改动factory这个类,我们最终的目的是只添加实体类,而工厂类和业务层代码不用动。

2. 静态工厂模式(同上)

  • 静态工厂只是把工厂类中的createCoffee变成了静态方法,而业务层直接使用CoffeeFactory.createCoffee获取对象
  • **总结:**这种模式本质上和简单工厂模式没什么区别

3. 工厂方法(无耦合)

  • 代码改动:将Factory变成了抽象接口,具体的实现交给实现类,说白了你有几个类就增加几个FactroyCoffee。

业务层代码:

java 复制代码
public class CoffeeStore {
    private CoffeeFactory coffeeFactory;
    public void setCoffeeFactory(CoffeeFactory coffeeFactory) {
        this.coffeeFactory = coffeeFactory;
    }
    public Coffee orderCoffer(){
        Coffee coffee = coffeeFactory.createCoffee();
        coffee.make();
        return coffee;
    }
}

工厂方法代码:

java 复制代码
// CoffeeFactory
public interface CoffeeFactory {

    public Coffee createCoffee();
}
// 具体实现例如 LatterFactory(拿铁咖啡)
public class LatterFactory implements CoffeeFactory{
    @Override
    public Coffee createCoffee() {
        return new LatterCoffee();
    }
}
  • 总结:工厂方法实现了业务层的完全解耦,工厂层也没有耦合了,如果以后想要增加一个类,只需要创建实体类和工厂的实现类,然后实现CoffeeFactory接口,只增加了2个类,对源代码无修改
  • 缺点:增加一个品种需要创建两个类,增加了系统复杂度,类爆炸

4. 抽象工厂模式

代码就不演示了~~ 核心思想就是工厂方法模式+抽象类

只不过将多个相似功能的Factory抽象到一个父类里面,例如咖啡店除了做咖啡还做甜品,2种咖啡2种甜品要创建4个类+4工厂+1个接口,我们可以把咖啡和甜品放到一个工厂里面,例如美式咖啡+美式甜品使用一个工厂,意式咖啡+意式甜品使用一个工厂,这样就创建4个类+2个工厂+1个接口

单例模式

1. 饿汉式

  • 因为对象是随类加载(线程安全)而创建的,所以天生就是线程安全
java 复制代码
class EHSingleton {
    // 饿汉式单例模式实现
    private EHSingleton(){}
    private static final EHSingleton instance = new EHSingleton();
    public static EHSingleton getInstance(){
        return instance;
    }
}

2. 懒汉式

1.1 线程不安全

java 复制代码
class LHsingletion {
    // 懒汉式单例模式
    private LHsingletion(){}
    private static LHsingletion instance;
    public static LHsingletion getInstance(){
        if (instance == null){ // 可能发生线程安全问题
            instance = new LHsingletion();
        }
        return instance;
    }
}

1.2 Double Check 线程安全方式

java 复制代码
class DoubleCheckSingletion{
    private DoubleCheckSingletion(){}
    private static DoubleCheckSingletion instance;
    public static DoubleCheckSingletion getInstance(){
        if (instance == null){
            synchronized (DoubleCheckSingletion.class) {
                if (instance == null) {
                    instance = new DoubleCheckSingletion();
                }
            }
        }
        return instance;
    }
}
相关推荐
圆山猫2 小时前
[Virtualization](四):Linux KVM/RISC-V 的 vCPU 运行路径
java·linux·risc-v
城管不管2 小时前
ReAct、Plan-and-Execute、Reflection 三大智能 Agent 范式核心区别
java·人工智能·算法·spring·ai·动态规划
IT小白杨2 小时前
从环境制备到自动化工作流:多账号运营的工程化架构拆解
java·经验分享·自动化·安全架构·指纹浏览器
豆瓣鸡3 小时前
算法日记 - Day3
java·开发语言·算法
萧瑟余晖3 小时前
Java深入解析篇九之NIO详解
java·网络·nio
The Chosen One9853 小时前
高进度算法模板速记(待完善)
java·前端·算法
极光代码工作室6 小时前
基于SpringBoot的课程预约系统
java·springboot·web开发·后端开发
Leighteen6 小时前
`try-finally` 里的 `return`:为什么 `finally` 会悄悄改掉返回值、吞掉异常
java·开发语言
名字还没想好☜7 小时前
Go 的 time.After 在 select 循环里内存泄漏:定时器堆积原理与 timer.Reset 正确姿势
java·数据库·golang·go·goroutine
圆山猫7 小时前
[Virtualization](三):RISC-V H-extension 与 Guest 执行模式
android·java·risc-v