设计模式面试

1.什么是设计模式?为什么要使用设计模式?

设计模式是一种解决问题的方案。

为什么要使用设计模式?

  • 提高代码复用性:经过验证的解决方案可以直接应用于类似问题
  • 提高可维护性:使代码更易于理解和修改
  • 提高扩展性:使系统更容易应对变化和增长

2.设计模式有哪些原则?

单一职责原则(SRP):一个类只应该有一个引起它变化的原因。一个类只负责一项职责。

开闭原则(OCP):软件中的对象(类、模块、函数等)应该对扩展开放,对修改关闭。通过扩展来实现变化,而不是修改现有代码。

依赖倒置原则(DIP):为了保证低耦合

  • 高层模块不应该依赖低层模块,二者都应该依赖抽象
  • 抽象不应该依赖细节,细节应该依赖抽象

3.工厂模式和策略模式的区别?

  • 目的不同:

    • 工厂模式的目的是创建对象,将对象的创建过程封装起来,使客户端的代码不需要依赖于具体类的实例化逻辑和使用逻辑。
    • 策略模式的目的是对于行为的封装和替换,使得客户端可以在运行时动态选择不同的算法。
  • 结构不同:

    • 工厂模式:抽象产品类+具体产品类
    • 策略模式:抽象策略类+具体策略类+上下文类(持有一个 抽象策略 的引用,并允许在运行时动态设置不同的策略

4.什么是单例模式的懒汉模式?为什么线程不安全?怎么解决?

单例模式的懒汉模式:延迟初始化,即直到第一次使用该实例时才进行实例化。

为什么线程不安全?

​ 如果两个线程同时调用 getInstance() 方法,获取实例,可能会创建多个实例,从而违反单例模式的原则。

如何使其线程安全?

  • 使用互斥锁(Mutex):可以在 getInstance 方法内部使用互斥锁来保证同一时刻只有一个线程能够执行实例化代码块。但是,这种方法每次获取实例都需要加锁和解锁,影响性能。

  • 双重检查锁定(Double-Checked Locking):为了减少不必要的同步开销,可以采用双重检查锁定的方法。首先检查是否已经实例化,如果没有,则进行加锁后再检查一次并实例化。

  • 使用局部静态变量(C++11及以上标准):C++11引入了对局部静态变量的支持,保证了其线程安全性,因此可以通过定义一个局部静态变量来实现懒汉模式下的线程安全单例。(局部静态变量只有第一次进入作用域时才初始化,且初始化具有原子性)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class Singleton {
    private:
    Singleton() {} // 构造函数私有化

    public:
    static Singleton& getInstance() {
    static Singleton instance; // 局部静态变量
    return instance;
    }

    Singleton(const Singleton&) = delete; // 禁止拷贝构造
    Singleton& operator=(const Singleton&) = delete; // 禁止赋值操作
    };