Skip to content

设计模式面试题

1. 设计模式的基本概念

问题:什么是设计模式?

答案

  • 设计模式:一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。
  • 作用
    • 提高代码的可重用性。
    • 提高代码的可读性。
    • 提高代码的可靠性。
    • 提高代码的可维护性。

2. 设计模式的分类

问题:设计模式有哪些分类?

答案

  • 创建型模式
    • 单例模式
    • 工厂方法模式
    • 抽象工厂模式
    • 建造者模式
    • 原型模式
  • 结构型模式
    • 适配器模式
    • 装饰器模式
    • 代理模式
    • 外观模式
    • 桥接模式
    • 组合模式
    • 享元模式
  • 行为型模式
    • 策略模式
    • 模板方法模式
    • 观察者模式
    • 迭代器模式
    • 责任链模式
    • 命令模式
    • 备忘录模式
    • 状态模式
    • 访问者模式
    • 中介者模式
    • 解释器模式

3. 单例模式

问题:什么是单例模式?如何实现?

答案

  • 单例模式:保证一个类只有一个实例,并提供一个访问它的全局访问点。
  • 实现方式
    • 饿汉式
    • 懒汉式
    • 双重检查锁
    • 静态内部类
    • 枚举

示例

java
// 饿汉式
public class Singleton {
    private static final Singleton instance = new Singleton();
    
    private Singleton() {
    }
    
    public static Singleton getInstance() {
        return instance;
    }
}

// 懒汉式
public class Singleton {
    private static Singleton instance;
    
    private Singleton() {
    }
    
    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

// 双重检查锁
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;
    }
}

// 静态内部类
public class Singleton {
    private Singleton() {
    }
    
    private static class Holder {
        private static final Singleton instance = new Singleton();
    }
    
    public static Singleton getInstance() {
        return Holder.instance;
    }
}

// 枚举
public enum Singleton {
    INSTANCE;
    
    public void method() {
    }
}

4. 工厂方法模式

问题:什么是工厂方法模式?

答案

  • 工厂方法模式:定义一个创建对象的接口,让子类决定实例化哪一个类。
  • 作用
    • 解耦对象的创建和使用。
    • 符合开闭原则。

示例

java
public interface Product {
    void use();
}

public class ConcreteProductA implements Product {
    @Override
    public void use() {
        System.out.println("Product A");
    }
}

public class ConcreteProductB implements Product {
    @Override
    public void use() {
        System.out.println("Product B");
    }
}

public abstract class Factory {
    public abstract Product createProduct();
}

public class ConcreteFactoryA extends Factory {
    @Override
    public Product createProduct() {
        return new ConcreteProductA();
    }
}

public class ConcreteFactoryB extends Factory {
    @Override
    public Product createProduct() {
        return new ConcreteProductB();
    }
}

5. 抽象工厂模式

问题:什么是抽象工厂模式?

答案

  • 抽象工厂模式:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
  • 作用
    • 解耦对象的创建和使用。
    • 符合开闭原则。
    • 支持产品族。

示例

java
public interface ProductA {
    void use();
}

public interface ProductB {
    void use();
}

public class ConcreteProductA1 implements ProductA {
    @Override
    public void use() {
        System.out.println("Product A1");
    }
}

public class ConcreteProductA2 implements ProductA {
    @Override
    public void use() {
        System.out.println("Product A2");
    }
}

public class ConcreteProductB1 implements ProductB {
    @Override
    public void use() {
        System.out.println("Product B1");
    }
}

public class ConcreteProductB2 implements ProductB {
    @Override
    public void use() {
        System.out.println("Product B2");
    }
}

public interface AbstractFactory {
    ProductA createProductA();
    ProductB createProductB();
}

public class ConcreteFactory1 implements AbstractFactory {
    @Override
    public ProductA createProductA() {
        return new ConcreteProductA1();
    }
    
    @Override
    public ProductB createProductB() {
        return new ConcreteProductB1();
    }
}

public class ConcreteFactory2 implements AbstractFactory {
    @Override
    public ProductA createProductA() {
        return new ConcreteProductA2();
    }
    
    @Override
    public ProductB createProductB() {
        return new ConcreteProductB2();
    }
}

6. 建造者模式

问题:什么是建造者模式?

答案

  • 建造者模式:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
  • 作用
    • 解耦对象的创建和使用。
    • 支持复杂对象的创建。
    • 支持不同的表示。

示例

java
public class Product {
    private String partA;
    private String partB;
    private String partC;
    
    public void setPartA(String partA) {
        this.partA = partA;
    }
    
    public void setPartB(String partB) {
        this.partB = partB;
    }
    
    public void setPartC(String partC) {
        this.partC = partC;
    }
    
    @Override
    public String toString() {
        return "Product{" + "partA='" + partA + '\'' + ", partB='" + partB + '\'' + ", partC='" + partC + '\'' + '}';
    }
}

public abstract class Builder {
    public abstract void buildPartA();
    public abstract void buildPartB();
    public abstract void buildPartC();
    public abstract Product getResult();
}

public class ConcreteBuilder extends Builder {
    private Product product = new Product();
    
    @Override
    public void buildPartA() {
        product.setPartA("Part A");
    }
    
    @Override
    public void buildPartB() {
        product.setPartB("Part B");
    }
    
    @Override
    public void buildPartC() {
        product.setPartC("Part C");
    }
    
    @Override
    public Product getResult() {
        return product;
    }
}

public class Director {
    private Builder builder;
    
    public Director(Builder builder) {
        this.builder = builder;
    }
    
    public void construct() {
        builder.buildPartA();
        builder.buildPartB();
        builder.buildPartC();
    }
}

// 使用
Builder builder = new ConcreteBuilder();
Director director = new Director(builder);
director.construct();
Product product = builder.getResult();

7. 原型模式

问题:什么是原型模式?

答案

  • 原型模式:通过复制现有的实例来创建新的实例,而不是通过new关键字。
  • 作用
    • 提高创建对象的效率。
    • 减少创建对象的资源消耗。
    • 支持动态创建对象。

示例

java
public class Prototype implements Cloneable {
    private String name;
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

// 使用
Prototype prototype1 = new Prototype();
prototype1.setName("Prototype 1");

Prototype prototype2 = (Prototype) prototype1.clone();
prototype2.setName("Prototype 2");

8. 适配器模式

问题:什么是适配器模式?

答案

  • 适配器模式:将一个类的接口转换成客户希望的另外一个接口。
  • 作用
    • 解耦接口。
    • 提高类的复用性。
    • 符合开闭原则。

示例

java
public interface Target {
    void request();
}

public class Adaptee {
    public void specificRequest() {
        System.out.println("Specific request");
    }
}

public class Adapter implements Target {
    private Adaptee adaptee;
    
    public Adapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }
    
    @Override
    public void request() {
        adaptee.specificRequest();
    }
}

// 使用
Target target = new Adapter(new Adaptee());
target.request();

9. 装饰器模式

问题:什么是装饰器模式?

答案

  • 装饰器模式:动态地给一个对象添加一些额外的职责,就增加功能来说,装饰器模式相比生成子类更为灵活。
  • 作用
    • 解耦职责。
    • 支持动态添加职责。
    • 符合开闭原则。

示例

java
public interface Component {
    void operation();
}

public class ConcreteComponent implements Component {
    @Override
    public void operation() {
        System.out.println("Concrete component");
    }
}

public abstract class Decorator implements Component {
    protected Component component;
    
    public Decorator(Component component) {
        this.component = component;
    }
    
    @Override
    public void operation() {
        component.operation();
    }
}

public class ConcreteDecoratorA extends Decorator {
    public ConcreteDecoratorA(Component component) {
        super(component);
    }
    
    @Override
    public void operation() {
        super.operation();
        System.out.println("Decorator A");
    }
}

public class ConcreteDecoratorB extends Decorator {
    public ConcreteDecoratorB(Component component) {
        super(component);
    }
    
    @Override
    public void operation() {
        super.operation();
        System.out.println("Decorator B");
    }
}

// 使用
Component component = new ConcreteComponent();
component = new ConcreteDecoratorA(component);
component = new ConcreteDecoratorB(component);
component.operation();

10. 代理模式

问题:什么是代理模式?

答案

  • 代理模式:为其他对象提供一种代理以控制对这个对象的访问。
  • 作用
    • 控制对象的访问。
    • 延迟加载。
    • 权限控制。

示例

java
public interface Subject {
    void request();
}

public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("Real subject");
    }
}

public class Proxy implements Subject {
    private RealSubject realSubject;
    
    @Override
    public void request() {
        if (realSubject == null) {
            realSubject = new RealSubject();
        }
        realSubject.request();
    }
}

// 使用
Subject subject = new Proxy();
subject.request();

11. 策略模式

问题:什么是策略模式?

答案

  • 策略模式:定义一系列算法,把它们一个个封装起来,并且使它们可相互替换。
  • 作用
    • 解耦算法和使用。
    • 支持动态切换算法。
    • 符合开闭原则。

示例

java
public interface Strategy {
    void execute();
}

public class ConcreteStrategyA implements Strategy {
    @Override
    public void execute() {
        System.out.println("Strategy A");
    }
}

public class ConcreteStrategyB implements Strategy {
    @Override
    public void execute() {
        System.out.println("Strategy B");
    }
}

public class Context {
    private Strategy strategy;
    
    public Context(Strategy strategy) {
        this.strategy = strategy;
    }
    
    public void execute() {
        strategy.execute();
    }
}

// 使用
Context context = new Context(new ConcreteStrategyA());
context.execute();

12. 模板方法模式

问题:什么是模板方法模式?

答案

  • 模板方法模式:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。
  • 作用
    • 提高代码复用性。
    • 支持子类扩展。
    • 符合开闭原则。

示例

java
public abstract class AbstractClass {
    public void templateMethod() {
        primitiveOperation1();
        primitiveOperation2();
    }
    
    protected abstract void primitiveOperation1();
    
    protected abstract void primitiveOperation2();
}

public class ConcreteClass extends AbstractClass {
    @Override
    protected void primitiveOperation1() {
        System.out.println("Operation 1");
    }
    
    @Override
    protected void primitiveOperation2() {
        System.out.println("Operation 2");
    }
}

// 使用
AbstractClass abstractClass = new ConcreteClass();
abstractClass.templateMethod();

13. 观察者模式

问题:什么是观察者模式?

答案

  • 观察者模式:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
  • 作用
    • 解耦对象。
    • 支持广播通信。
    • 符合开闭原则。

示例

java
public interface Observer {
    void update(String message);
}

public interface Subject {
    void registerObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers(String message);
}

public class ConcreteSubject implements Subject {
    private List<Observer> observers = new ArrayList<>();
    
    @Override
    public void registerObserver(Observer observer) {
        observers.add(observer);
    }
    
    @Override
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }
    
    @Override
    public void notifyObservers(String message) {
        for (Observer observer : observers) {
            observer.update(message);
        }
    }
}

public class ConcreteObserver implements Observer {
    @Override
    public void update(String message) {
        System.out.println("Received: " + message);
    }
}

// 使用
Subject subject = new ConcreteSubject();
Observer observer = new ConcreteObserver();
subject.registerObserver(observer);
subject.notifyObservers("Hello");

14. 责任链模式

问题:什么是责任链模式?

答案

  • 责任链模式:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。
  • 作用
    • 解耦请求和处理。
    • 支持动态添加处理者。
    • 符合开闭原则。

示例

java
public abstract class Handler {
    protected Handler next;
    
    public Handler setNext(Handler next) {
        this.next = next;
        return next;
    }
    
    public abstract void handle(String request);
}

public class ConcreteHandlerA extends Handler {
    @Override
    public void handle(String request) {
        if (request.equals("A")) {
            System.out.println("Handle A");
        } else if (next != null) {
            next.handle(request);
        }
    }
}

public class ConcreteHandlerB extends Handler {
    @Override
    public void handle(String request) {
        if (request.equals("B")) {
            System.out.println("Handle B");
        } else if (next != null) {
            next.handle(request);
        }
    }
}

// 使用
Handler handlerA = new ConcreteHandlerA();
Handler handlerB = new ConcreteHandlerB();
handlerA.setNext(handlerB);
handlerA.handle("A");

15. 命令模式

问题:什么是命令模式?

答案

  • 命令模式:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化。
  • 作用
    • 解耦请求和执行。
    • 支持撤销和重做。
    • 符合开闭原则。

示例

java
public interface Command {
    void execute();
}

public class ConcreteCommand implements Command {
    private Receiver receiver;
    
    public ConcreteCommand(Receiver receiver) {
        this.receiver = receiver;
    }
    
    @Override
    public void execute() {
        receiver.action();
    }
}

public class Receiver {
    public void action() {
        System.out.println("Receiver action");
    }
}

public class Invoker {
    private Command command;
    
    public void setCommand(Command command) {
        this.command = command;
    }
    
    public void execute() {
        command.execute();
    }
}

// 使用
Receiver receiver = new Receiver();
Command command = new ConcreteCommand(receiver);
Invoker invoker = new Invoker();
invoker.setCommand(command);
invoker.execute();

16. 状态模式

问题:什么是状态模式?

答案

  • 状态模式:允许一个对象在其内部状态改变时改变它的行为。
  • 作用
    • 解耦状态和行为。
    • 支持动态切换状态。
    • 符合开闭原则。

示例

java
public interface State {
    void handle();
}

public class ConcreteStateA implements State {
    @Override
    public void handle() {
        System.out.println("State A");
    }
}

public class ConcreteStateB implements State {
    @Override
    public void handle() {
        System.out.println("State B");
    }
}

public class Context {
    private State state;
    
    public void setState(State state) {
        this.state = state;
    }
    
    public void handle() {
        state.handle();
    }
}

// 使用
Context context = new Context();
context.setState(new ConcreteStateA());
context.handle();

17. 设计模式的原则

问题:设计模式有哪些原则?

答案

  • 单一职责原则:一个类只负责一项职责。
  • 开闭原则:对扩展开放,对修改关闭。
  • 里氏替换原则:子类可以替换父类。
  • 接口隔离原则:使用多个专门的接口,而不是单一的总接口。
  • 依赖倒置原则:依赖抽象而不是具体实现。

18. 设计模式的应用场景

问题:如何选择设计模式?

答案

  • 单例模式:需要唯一实例的场景。
  • 工厂方法模式:需要创建对象的场景。
  • 抽象工厂模式:需要创建产品族的场景。
  • 建造者模式:需要创建复杂对象的场景。
  • 原型模式:需要复制对象的场景。
  • 适配器模式:需要接口转换的场景。
  • 装饰器模式:需要动态添加职责的场景。
  • 代理模式:需要控制对象访问的场景。
  • 策略模式:需要切换算法的场景。
  • 模板方法模式:需要定义算法骨架的场景。
  • 观察者模式:需要一对多通知的场景。
  • 责任链模式:需要处理请求链的场景。
  • 命令模式:需要封装请求的场景。
  • 状态模式:需要切换状态的场景。

19. 设计模式的优缺点

问题:设计模式有什么优缺点?

答案

  • 优点
    • 提高代码的可重用性。
    • 提高代码的可读性。
    • 提高代码的可靠性。
    • 提高代码的可维护性。
  • 缺点
    • 增加代码的复杂性。
    • 增加类的数量。
    • 增加系统的开销。

20. 设计模式的最佳实践

问题:使用设计模式的最佳实践有哪些?

答案

  • 根据场景选择合适的设计模式。
  • 不要过度使用设计模式。
  • 遵循设计模式的原则。
  • 理解设计模式的意图。
  • 灵活运用设计模式。
  • 避免为了使用设计模式而使用设计模式。
  • 保持代码的简洁性。
  • 保持代码的可读性。
  • 保持代码的可维护性。
  • 保持代码的可扩展性。