java面试——讲一下常用的设计模式

设计模式分类

设计模式(Design Patterns)是软件开发中常见问题的可重用解决方案。设计模式由 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides(被称为“四人帮”或 ​GoF)在其经典著作《设计模式:可复用面向对象软件的基础》中首次系统化地介绍。GoF 设计模式共分为 ​23 种,并根据其用途分为三大类:

1. 创建型模式(Creational Patterns)

这类模式关注对象的创建机制,试图以适合情况的方式创建对象,使系统独立于对象的创建、组合和表示。

  1. 工厂方法模式(Factory Method Pattern)​
  2. 抽象工厂模式(Abstract Factory Pattern)​
  3. 单例模式(Singleton Pattern)​
  4. 建造者模式(Builder Pattern)​
  5. 原型模式(Prototype Pattern)​

2. 结构型模式(Structural Patterns)

这类模式关注类和对象的组合,以形成更大的结构,同时确保结构的灵活性和效率。

  1. 适配器模式(Adapter Pattern)​
  2. 桥接模式(Bridge Pattern)​
  3. 组合模式(Composite Pattern)​
  4. 装饰者模式(Decorator Pattern)​
  5. 外观模式(Facade Pattern)​
  6. 享元模式(Flyweight Pattern)​
  7. 代理模式(Proxy Pattern)​

3. 行为型模式(Behavioral Patterns)

这类模式关注对象之间的责任分配和通信,旨在提高系统的灵活性和可维护性。

  1. 责任链模式(Chain of Responsibility Pattern)​
  2. 命令模式(Command Pattern)​
  3. 解释器模式(Interpreter Pattern)​
  4. 迭代器模式(Iterator Pattern)​
  5. 中介者模式(Mediator Pattern)​
  6. 备忘录模式(Memento Pattern)​
  7. 观察者模式(Observer Pattern)​
  8. 状态模式(State Pattern)​
  9. 策略模式(Strategy Pattern)​
  10. 模板方法模式(Template Method Pattern)​
  11. 访问者模式(Visitor Pattern)​

其他常见设计模式

除了 GoF 提出的 23 种设计模式外,随着软件开发的发展,许多其他设计模式也被提出并广泛应用于不同场景。例如:

  • 并发模式(Concurrency Patterns)​

    • 生产者-消费者模式(Producer-Consumer Pattern)
    • 读写锁模式(Read-Write Lock Pattern)
    • 信号量模式(Semaphore Pattern)
  • 架构模式(Architectural Patterns)​

    • MVC 模式(Model-View-Controller)
    • MVVM 模式(Model-View-ViewModel)
    • 微服务架构模式(Microservices Architecture Pattern)
  • 企业集成模式(Enterprise Integration Patterns)​

    • 消息通道模式(Message Channel Pattern)
    • 消息路由器模式(Message Router Pattern)
    • 事务模式(Transaction Pattern)

这些模式虽然不属于 GoF 的 23 种设计模式,但在实际开发中也具有重要的指导意义。


总结

  • GoF 设计模式:23 种,分为创建型、结构型和行为型三大类。
  • 其他设计模式:随着技术的发展,许多新的设计模式被提出,扩展了设计模式的范畴,以适应不同的开发需求和场景。

理解并熟练应用这些设计模式,可以显著提高代码的可维护性、可复用性和灵活性,是每个软件开发人员必备的技能之一。

常用设计模式详细介绍

设计模式通常分为三大类:​创建型模式结构型模式 和 ​行为型模式。下面我们将详细介绍常用的设计模式。


一、创建型模式(Creational Patterns)

创建型模式主要关注对象的创建机制,试图以适合情况的方式创建对象,隐藏对象创建的复杂性。

1. 单例模式(Singleton Pattern)

定义:确保一个类只有一个实例,并提供一个全局访问点。
应用场景:日志记录器、数据库连接池、配置管理器等。
实现方式

  • 懒汉式:延迟初始化,线程不安全。
  • 饿汉式:类加载时就初始化,线程安全。
  • 双重检查锁定(Double-Checked Locking):线程安全且延迟初始化。
  • 静态内部类:利用类加载机制保证线程安全。
  • 枚举:线程安全,防止反射攻击。
public class Singleton {
    private static Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

2. 工厂模式(Factory Pattern)

定义:定义一个创建对象的接口,但由子类决定实例化哪个类。工厂方法让类的实例化推迟到子类。
应用场景:对象创建逻辑复杂,需要解耦对象的创建和使用。
实现方式

  • 简单工厂模式:通过一个工厂类创建对象。
  • 工厂方法模式:定义工厂接口,由子类实现具体的工厂方法。
  • 抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
// 工厂方法模式示例
interface Product {}
class ConcreteProductA implements Product {}
class ConcreteProductB implements Product {}

interface Factory {
    Product createProduct();
}

class ConcreteFactoryA implements Factory {
    public Product createProduct() {
        return new ConcreteProductA();
    }
}

class ConcreteFactoryB implements Factory {
    public Product createProduct() {
        return new ConcreteProductB();
    }
}

3. 建造者模式(Builder Pattern)

定义:将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。
应用场景:对象构造过程复杂,需要灵活控制对象的创建过程。
实现方式:通过一个指挥者类和多个具体建造者类来构建对象。

// 建造者模式示例
class Product {
    private String partA;
    private String partB;

    public void setPartA(String partA) { this.partA = partA; }
    public void setPartB(String partB) { this.partB = partB; }
}

interface Builder {
    void buildPartA();
    void buildPartB();
    Product getResult();
}

class ConcreteBuilder implements Builder {
    private Product product = new Product();

    public void buildPartA() { product.setPartA("PartA"); }
    public void buildPartB() { product.setPartB("PartB"); }
    public Product getResult() { return product; }
}

class Director {
    private Builder builder;

    public Director(Builder builder) { this.builder = builder; }

    public void construct() {
        builder.buildPartA();
        builder.buildPartB();
    }
}

4. 原型模式(Prototype Pattern)

定义:通过复制现有的实例来创建新的实例,而不是通过新建实例。
应用场景:对象创建成本高,或者需要动态配置对象属性。
实现方式:实现 Cloneable 接口,重写 clone() 方法。

// 原型模式示例
class Prototype implements Cloneable {
    private String field;

    public Prototype(String field) { this.field = field; }
    public void setField(String field) { this.field = field; }
    public String getField() { return field; }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

二、结构型模式(Structural Patterns)

结构型模式主要关注类和对象的组合,以形成更大的结构。

1. 适配器模式(Adapter Pattern)

定义:将一个类的接口转换成客户希望的另一个接口,使得原本由于接口不兼容而不能一起工作的类可以一起工作。
应用场景:需要复用已有的类,但其接口不符合需求。
实现方式:类适配器(继承)和对象适配器(组合)。

// 适配器模式示例
interface Target {
    void request();
}

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

class Adapter implements Target {
    private Adaptee adaptee;

    public Adapter(Adaptee adaptee) { this.adaptee = adaptee; }

    @Override
    public void request() {
        adaptee.specificRequest();
    }
}

2. 装饰器模式(Decorator Pattern)

定义:动态地给一个对象添加一些额外的职责,就增加功能来说,装饰器模式比生成子类更为灵活。
应用场景:需要在不修改现有对象结构的情况下,动态地扩展对象的功能。
实现方式:通过装饰器类包装原始对象,装饰器类与原始对象实现相同的接口。

// 装饰器模式示例
interface Component {
    void operation();
}

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

class Decorator implements Component {
    private Component component;

    public Decorator(Component component) { this.component = component; }

    @Override
    public void operation() {
        component.operation();
    }
}

class ConcreteDecoratorA extends Decorator {
    public ConcreteDecoratorA(Component component) { super(component); }

    @Override
    public void operation() {
        super.operation();
        System.out.println("Decorator A");
    }
}

3. 代理模式(Proxy Pattern)

定义:为其他对象提供一个代理以控制对这个对象的访问。
应用场景:需要在访问对象时进行一些额外的操作,如权限验证、延迟加载等。
实现方式:静态代理和动态代理。

// 代理模式示例
interface Subject {
    void request();
}

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

class Proxy implements Subject {
    private RealSubject realSubject;

    public Proxy(RealSubject realSubject) { this.realSubject = realSubject; }

    @Override
    public void request() {
        System.out.println("Proxy Pre-processing");
        realSubject.request();
        System.out.println("Proxy Post-processing");
    }
}

4. 外观模式(Facade Pattern)

定义:为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,使得这一子系统更加容易使用。
应用场景:简化复杂系统的接口,提供一个简单的入口。
实现方式:通过外观类封装子系统的复杂性。

// 外观模式示例
class SubsystemA { public void operationA() { System.out.println("Subsystem A"); } }
class SubsystemB { public void operationB() { System.out.println("Subsystem B"); } }

class Facade {
    private SubsystemA subsystemA;
    private SubsystemB subsystemB;

    public Facade() {
        subsystemA = new SubsystemA();
        subsystemB = new SubsystemB();
    }

    public void operation() {
        subsystemA.operationA();
        subsystemB.operationB();
    }
}

三、行为型模式(Behavioral Patterns)

行为型模式主要关注对象之间的责任分配和通信。

1. 观察者模式(Observer Pattern)

定义:定义对象间的一对多依赖关系,当一个对象改变状态时,其所有依赖者都会收到通知并自动更新。
应用场景:事件驱动系统、消息通知系统等。
实现方式:通过主题(Subject)和观察者(Observer)接口实现。

// 观察者模式示例
import java.util.ArrayList;
import java.util.List;

interface Observer {
    void update(String message);
}

class ConcreteObserver implements Observer {
    private String name;

    public ConcreteObserver(String name) { this.name = name; }

    @Override
    public void update(String message) {
        System.out.println(name + " received: " + message);
    }
}

class Subject {
    private List<Observer> observers = new ArrayList<>();

    public void addObserver(Observer observer) { observers.add(observer); }
    public void removeObserver(Observer observer) { observers.remove(observer); }

    public void notifyObservers(String message) {
        for (Observer observer : observers) {
            observer.update(message);
        }
    }
}

2. 策略模式(Strategy Pattern)

定义:定义一系列算法,将每个算法封装起来,并使它们可以互换。策略模式让算法独立于使用它的客户而变化。
应用场景:需要在运行时选择不同的算法或行为。
实现方式:通过策略接口和具体策略类实现。

// 策略模式示例
interface Strategy {
    void execute();
}

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

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

class Context {
    private Strategy strategy;

    public Context(Strategy strategy) { this.strategy = strategy; }

    public void executeStrategy() {
        strategy.execute();
    }
}

3. 状态模式(State Pattern)

定义:允许对象在其内部状态改变时改变其行为,对象看起来似乎修改了其类。
应用场景:对象的行为依赖于其状态,并且状态转换逻辑复杂。
实现方式:通过状态接口和具体状态类实现。

// 状态模式示例
interface State {
    void handle();
}

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

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

class Context {
    private State state;

    public void setState(State state) { this.state = state; }
    public void request() { state.handle(); }
}

4. 命令模式(Command Pattern)

定义:将请求封装为对象,从而使你可以用不同的请求对客户进行参数化,并且支持请求的排队、记录日志、撤销等操作。
应用场景:需要将请求的发送者和接收者解耦,或者需要支持撤销操作。
实现方式:通过命令接口和具体命令类实现。

// 命令模式示例
interface Command {
    void execute();
}

class ConcreteCommand implements Command {
    private Receiver receiver;

    public ConcreteCommand(Receiver receiver) { this.receiver = receiver; }

    @Override
    public void execute() {
        receiver.action();
    }
}

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

class Invoker {
    private Command command;

    public void setCommand(Command command) { this.command = command; }
    public void executeCommand() { command.execute(); }
}

5. 迭代器模式(Iterator Pattern)

定义:提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。
应用场景:需要遍历集合对象,但不希望暴露其内部结构。
实现方式:通过迭代器接口和具体迭代器类实现。

// 迭代器模式示例
import java.util.ArrayList;
import java.util.List;

interface Iterator {
    boolean hasNext();
    Object next();
}

class ConcreteIterator implements Iterator {
    private List<Object> list = new ArrayList<>();
    private int index = 0;

    public ConcreteIterator(List<Object> list) { this.list = list; }

    @Override
    public boolean hasNext() { return index < list.size(); }

    @Override
    public Object next() { return list.get(index++); }
}

class Aggregate {
    private List<Object> list = new ArrayList<>();

    public void add(Object obj) { list.add(obj); }
    public Iterator createIterator() { return new ConcreteIterator(list); }
}

四、其他常用设计模式

1. 中介者模式(Mediator Pattern)

定义:用一个中介对象来封装一系列对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散。
应用场景:对象之间的交互复杂,需要解耦。

2. 备忘录模式(Memento Pattern)

定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后可以将该对象恢复到原先保存的状态。
应用场景:需要保存和恢复对象的状态。

3. 访问者模式(Visitor Pattern)

定义:表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
应用场景:需要对一个复杂对象结构中的元素进行操作,且操作与元素类解耦。

4. 组合模式(Composite Pattern)

定义:将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。
应用场景:处理树形结构的数据,如文件系统、组织架构等。

5. 桥接模式(Bridge Pattern)

定义:将抽象部分与它的实现部分分离,使它们都可以独立地变化。
应用场景:需要将抽象与实现解耦,使两者可以独立扩展。


总结

设计模式是软件开发中的最佳实践,不同的设计模式适用于不同的场景。理解并掌握这些设计模式,可以帮助开发者编写出更加灵活、可维护和可扩展的代码。在实际开发中,应根据具体需求选择合适的设计模式,避免过度设计。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值