设计模式面试题(一)

时间:2024-04-03 07:06:38

1.设计模式的六大原则是什么

设计模式的六大原则,通常被视为面向对象设计的基石,旨在指导如何创建易于维护、扩展和复用的软件。这些原则包括:

1. 单一职责原则(Single Responsibility Principle, SRP)

一个类应该仅有一个引起它变化的原因。这个原则强调一个类应该专注于做一件事情,这样它就只有一个变化的原因。这有助于使类更加紧凑和可维护。

2. 开放封闭原则(Open/Closed Principle, OCP)

软件实体(类、模块、函数等)应该是可扩展的,但是不可修改。这意味着当应用的需求改变或者新的功能被引入时,应该能够在不修改现有代码的情况下扩展模块的行为。

3. 里氏替换原则(Liskov Substitution Principle, LSP)

子类型必须能够替换掉它们的基类型。这个原则是关于多态和继承的,确保子类可以替换父类而不会破坏程序的行为。

4. 依赖倒置原则(Dependency Inversion Principle, DIP)

高层模块不应该依赖低层模块,两者都应该依赖于抽象;抽象不应该依赖于细节,细节应该依赖于抽象。这个原则鼓励使用接口和抽象类来达到解耦的目的,从而提高系统的复用性和灵活性。

5. 接口隔离原则(Interface Segregation Principle, ISP)

客户端不应该*依赖于它们不使用的接口。这个原则鼓励将大接口拆分成更小和更具体的接口,使得实现类只需要关心它们真正需要的接口。

6. 迪米特法则(Law of Demeter, LoD)/最少知识原则(Principle of Least Knowledge)

一个对象应该对其他对象保持最少的了解。这个原则鼓励减少对象之间的交互,避免创建高度耦合的设计。简单来说,尽量减少直接的朋友关系,避免和陌生人说话。

这些原则不是孤立使用的,它们相互之间有着紧密的联系。在实际的软件开发过程中,合理地应用这些原则可以帮助开发者设计出更加灵活、可维护和易于扩展的系统。

2.什么是单例

单例(Singleton)模式是一种设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取该实例。单例模式通常用于管理共享资源,如数据库连接或文件系统,以及在应用程序中实现全局状态或配置信息的管理。

实现单例模式的关键点包括:

  1. 私有构造函数:确保外部代码不能直接构造类的实例。
  2. 私有静态实例变量:类本身持有自己类型的私有静态实例。
  3. 公共静态方法:提供一个全局访问点,外部代码通过这个方法获取类的唯一实例。这个方法通常包含逻辑以创建实例(如果实例不存在的话)。

常见的单例实现方式:

  1. 懒汉式:实例在第一次被请求时创建。这种方式支持延迟加载,但需要处理多线程访问的同步问题。
public class Singleton {
    private static Singleton instance;

    private Singleton() {}

    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}
  1. 饿汉式:实例在类被加载时创建。这种方式不需要考虑多线程问题,实现简单,但不支持延迟加载。
public class Singleton {
    private static final Singleton instance = new Singleton();

    private Singleton() {}

    public static Singleton getInstance() {
        return instance;
    }
}
  1. 双重检查锁定(Double-Checked Locking):在懒汉式的基础上增加了双重检查,以减少同步开销。
public class Singleton {
    private static volatile Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}
  1. 静态内部类:利用类加载机制保证实例的唯一性和线程安全。
public class Singleton {
    private Singleton() {}

    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

单例模式的优点:

  • 对于频繁使用的对象,可以省略创建对象所花费的时间,这对于重量级对象而言,是一个大优势。
  • 由于单例模式只生成一个实例,减少了系统性能的开销,尤其是当一个对象的产生需要比较多资源时,如读取配置、产生其他依赖对象时。
  • 可以全局访问。

单例模式的缺点:

  • 单例类的职责过重,违反了“单一职责原则”。
  • 单例模式一般没有接口,扩展困难,如果要扩展单例对象,只有修改代码,违背了“开闭原则”。
  • 在多线程环境下,必须处理好多线程同步问题,特别是当单例模式的实现没有考虑线程安全问题时,可能会导致多个实例被创建。

单例模式是一种非常有用的模式,但在使用时应当考虑其对系统设计的影响。

3.哪些地方用到了单例模式

单例模式因其提供了一种控制实例数目、节省资源和提供全局访问点的方式,在软件开发中被广泛使用。以下是一些常见的单例模式应用场景:

1. 日志类

单例模式常用于日志管理,确保全局有一个日志类实例来收集和输出日志信息。这有助于统一管理日志配置和访问方式,使得从应用的任何部分都可以方便地记录日志。

2. 配置管理器

应用程序的配置信息通常被集中管理,以便于修改和访问。使用单例模式可以确保配置信息在内存中只有一个副本,无论它在应用程序中的哪个位置被访问。

3. 连接池

数据库连接池、线程池等资源池经常使用单例模式实现,以便于资源的重复利用和管理。单例模式确保全局只有一个资源池实例,从而避免重复创建消耗性能的资源。

4. 硬件接口访问

对于访问有限资源的硬件接口,如打印机、串口等,使用单例模式可以避免对同一硬件资源的冲突访问。

5. 应用程序中的缓存

应用程序级别的缓存,如Web应用的会话缓存、经常被访问对象的缓存等,可以使用单例模式实现。这样可以确保缓存数据的全局唯一性和一致性。

6. 操作系统的文件系统

操作系统中,文件系统的访问接口也常常设计为单例模式,以确保对文件系统资源的统一管理。

7. 应用程序的全局状态或服务

像全局状态管理器、服务注册中心等核心组件,通常也会使用单例模式来实现,以保证这些关键资源在应用程序范围内的唯一性和可控性。

8. 设计模式实现

在实现某些设计模式时,如工厂模式、抽象工厂模式中的工厂类,有时也会使用单例模式来确保全局仅有一个工厂实例,负责产生其他对象。

结论

单例模式因其简单和实用,在软件开发中有广泛的应用。然而,也需要注意它的使用场景和潜在的问题,如在多线程环境下的安全问题,以及可能导致的程序设计上的不灵活性。正确理解和使用单例模式,可以帮助开发高效、可维护的软件系统。