Java设计模式详细讲解

74 篇文章 2 订阅

目录

  1. 设计模式概述

  2. 创建型模式

  3. 结构型模式

  4. 行为型模式

  5. 设计模式的应用与实践

  6. 设计模式的扩展与创新

  7. 总结


1. 设计模式概述

1.1 什么是设计模式

设计模式是一套被反复使用的、为特定问题提供解决方案的模板。它们是经过总结和优化的、被业界广泛认可的、用于软件设计中的最佳实践。设计模式并不是具体的代码,而是解决特定设计问题的通用方案。它们帮助开发者避免在编写代码时遇到常见的问题,并且通过模式化的思维提升代码的可读性、可维护性和可扩展性。

1.2 设计模式的类型

设计模式可以分为三大类:创建型模式、结构型模式和行为型模式。

  • 创建型模式:关注对象的创建,确保对象的创建过程是高效且灵活的。主要包括单例模式、工厂方法模式、抽象工厂模式、建造者模式和原型模式。
  • 结构型模式:关注类和对象的组合,通过继承或接口来实现结构的灵活性。主要包括适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式和享元模式。
  • 行为型模式:关注对象之间的职责分配和通信。主要包括策略模式、模板方法模式、观察者模式、迭代器模式、责任链模式、命令模式、备忘录模式、状态模式、中介者模式、访问者模式和解释器模式。

1.3 设计模式的历史与发展

设计模式的概念最早由Christopher Alexander在建筑领域提出,后来由Erich Gamma等人引入软件工程。1994年,四位作者(被称为“四人帮”或GoF)出版了《设计模式:可复用面向对象软件的基础》一书,系统性地整理了23种设计模式,从此设计模式成为软件开发中的经典理论之一。

1.4 设计模式在软件开发中的重要性

设计模式通过提供可复用的解决方案,帮助开发者编写更高质量的代码。它们促进了代码的模块化设计,使得软件更加灵活和可维护。同时,设计模式作为一种通用的设计语言,也促进了开发团队之间的沟通和协作。

2. 创建型模式

2.1 单例模式

单例模式(Singleton Pattern)确保一个类只有一个实例,并提供一个全局访问点。它通常用于管理全局状态或控制资源访问。

代码示例

public class Singleton {
    private static Singleton instance;

    private Singleton() {}

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

扩展

  • 讨论单例模式的懒汉式、饿汉式、双重检查锁定(DCL)以及枚举单例的实现。
  • 分析单例模式的优缺点,尤其是多线程环境下的线程安全问题。
  • 提供在实际项目中的应用场景,如数据库连接池、日志系统等。

2.2 工厂方法模式

工厂方法模式(Factory Method Pattern)定义一个创建对象的接口,但让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。

代码示例

public interface Product {
    void use();
}

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

public class ConcreteFactory {
    public Product createProduct(String type) {
        if (type.equals("A")) {
            return new ConcreteProductA();
        }
        // 可以扩展其他产品类型的创建逻辑
        return null;
    }
}

扩展

  • 讨论工厂方法模式的变体,如静态工厂方法。
  • 分析工厂方法模式的优缺点,尤其是当产品种类增加时的扩展性。
  • 提供在实际项目中的应用场景,如复杂对象的创建、依赖注入等。

2.3 抽象工厂模式

抽象工厂模式(Abstract Factory Pattern)提供一个接口,用于创建相关或依赖对象的家族,而无需指定具体类。

代码示例

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

public class ConcreteFactory1 implements AbstractFactory {
    public ProductA createProductA() {
        return new ProductA1();
    }
    public ProductB createProductB() {
        return new ProductB1();
    }
}

扩展

  • 讨论抽象工厂模式在构建复杂系统时如何提供一致的产品家族。
  • 分析抽象工厂模式的优缺点,尤其是当产品家族扩展时的可维护性。
  • 提供在实际项目中的应用场景,如跨平台应用、GUI库等。

2.4 建造者模式

建造者模式(Builder Pattern)将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。

代码示例

public class Product {
    private String part1;
    private String part2;



    public void setPart1(String part1) { this.part1 = part1; }
    public void setPart2(String part2) { this.part2 = part2; }
}

public class ProductBuilder {
    private Product product = new Product();

    public ProductBuilder buildPart1(String part1) {
        product.setPart1(part1);
        return this;
    }

    public ProductBuilder buildPart2(String part2) {
        product.setPart2(part2);
        return this;
    }

    public Product build() {
        return product;
    }
}

扩展

  • 讨论建造者模式如何改善代码的可读性和对象的创建复杂性。
  • 分析建造者模式的优缺点,尤其是在构建具有多个可选参数的对象时的优势。
  • 提供在实际项目中的应用场景,如创建复杂的配置对象、消息对象等。

2.5 原型模式

原型模式(Prototype Pattern)通过复制现有对象来创建新对象,避免了创建新对象的复杂性和开销。

代码示例

public class Prototype implements Cloneable {
    private String state;

    public Prototype clone() {
        try {
            return (Prototype) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
            return null;
        }
    }

    public void setState(String state) { this.state = state; }
    public String getState() { return state; }
}

扩展

  • 讨论原型模式在创建复杂对象时如何提高性能和灵活性。
  • 分析原型模式的优缺点,尤其是在深拷贝和浅拷贝时的注意事项。
  • 提供在实际项目中的应用场景,如对象的快速复制、缓存等。

3. 结构型模式

3.1 适配器模式

适配器模式(Adapter Pattern)将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

代码示例

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;
    }

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

扩展

  • 讨论类适配器与对象适配器的区别和应用场景。
  • 分析适配器模式的优缺点,尤其是在处理遗留代码和第三方库时的灵活性。
  • 提供在实际项目中的应用场景,如不同接口的兼容、API集成等。

3.2 装饰器模式

装饰器模式(Decorator Pattern)动态地给一个对象添加一些额外的职责,就增加功能来说,装饰器模式相比生成子类更为灵活。

代码示例

public interface Component {
    void operation();
}

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

public class Decorator implements Component {
    private Component component;

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

    public void operation() {
        component.operation();
        System.out.println("Decorator added behavior");
    }
}

扩展

  • 讨论装饰器模式如何替代继承进行功能扩展,避免了子类爆炸。
  • 分析装饰器模式的优缺点,尤其是在对象扩展时的灵活性。
  • 提供在实际项目中的应用场景,如日志记录、数据校验、动态增强功能等。

3.3 代理模式

代理模式(Proxy Pattern)为其他对象提供一种代理以控制对这个对象的访问。

代码示例

public interface Subject {
    void request();
}

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

public class Proxy implements Subject {
    private RealSubject realSubject;

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

    public void request() {
        System.out.println("Proxy request");
        realSubject.request();
    }
}

扩展

  • 讨论静态代理与动态代理的实现与应用场景。
  • 分析代理模式的优缺点,尤其是在安全控制和性能优化中的作用。
  • 提供在实际项目中的应用场景,如远程代理、安全代理、虚拟代理等。

3.4 外观模式

外观模式(Facade Pattern)为子系统中的一组接口提供一个一致的界面,使得子系统更容易使用。

代码示例

public class SubsystemA {
    public void operationA() {
        System.out.println("SubsystemA operation");
    }
}

public class SubsystemB {
    public void operationB() {
        System.out.println("SubsystemB operation");
    }
}

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

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

扩展

  • 讨论外观模式如何简化复杂系统的接口,隐藏子系统的复杂性。
  • 分析外观模式的优缺点,尤其是在大型系统中的应用。
  • 提供在实际项目中的应用场景,如模块化系统的接口封装、API设计等。

3.5 桥接模式

桥接模式(Bridge Pattern)将抽象部分与它的实现部分分离,使它们都可以独立地变化。

代码示例

public interface Implementor {
    void operationImpl();
}

public class ConcreteImplementorA implements Implementor {
    public void operationImpl() {
        System.out.println("ConcreteImplementorA operation");
    }
}

public abstract class Abstraction {
    protected Implementor implementor;

    public Abstraction(Implementor implementor) {
        this.implementor = implementor;
    }

    public abstract void operation();
}

public class RefinedAbstraction extends Abstraction {
    public RefinedAbstraction(Implementor implementor) {
        super(implementor);
    }

    public void operation() {
        implementor.operationImpl();
    }
}

扩展

  • 讨论桥接模式如何实现抽象与实现的分离,增强系统的扩展性。
  • 分析桥接模式的优缺点,尤其是在应对多维度变化时的优势。
  • 提供在实际项目中的应用场景,如跨平台应用、设备驱动程序等。

3.6 组合模式

组合模式(Composite Pattern)将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

代码示例

public interface Component {
    void operation();
}

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

public class Composite implements Component {
    private List<Component> children = new ArrayList<>();

    public void add(Component component) {
        children.add(component);
    }

    public void operation() {
        for (Component child : children) {
            child.operation();
        }
    }
}

扩展

  • 讨论组合模式如何处理树形结构中的复杂关系,使得对象的组合与单个对象操作一致。
  • 分析组合模式的优缺点,尤其是在处理递归结构时的灵活性。
  • 提供在实际项目中的应用场景,如文件系统、GUI组件树等。

3.7 享元模式

享元模式(Flyweight Pattern)通过共享技术来有效地支持大量细粒度对象的复用。

代码示例

public class Flyweight {
    private String intrinsicState;

    public Flyweight(String intrinsicState) {
        this.intrinsicState = intrinsicState;
    }

    public void operation(String extrinsicState) {
        System.out.println("IntrinsicState: " + intrinsicState + ", ExtrinsicState: " + extrinsicState);
    }
}

public class FlyweightFactory {
    private Map<String, Flyweight> flyweights = new HashMap<>();

    public Flyweight getFlyweight(String key) {
        if (!flyweights.containsKey(key)) {
            flyweights.put(key, new Flyweight(key));
        }
        return flyweights.get(key);
    }
}

扩展

  • 讨论享元模式如何减少内存占用,提高系统性能,特别是在对象创建开销较大的场景中。
  • 分析享元模式的优缺点,尤其是在状态管理和性能优化中的应用。
  • 提供在实际项目中的应用场景,如字符处理、对象池等。

4. 行为型模式

4.1 策略模式

策略模式(Strategy Pattern)定义了一系列算法,将每一个算法封装起来,并使它们可以相互替换。策略模式使得算法可以独立于使用它的客户端而变化。

代码示例

public interface Strategy {


    void algorithm();
}

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

public class Context {
    private Strategy strategy;

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

    public void executeAlgorithm() {
        strategy.algorithm();
    }
}

扩展

  • 讨论策略模式如何通过组合代替继承,减少代码的耦合度。
  • 分析策略模式的优缺点,尤其是在动态选择算法时的灵活性。
  • 提供在实际项目中的应用场景,如支付方式选择、排序算法等。

4.2 模板方法模式

模板方法模式(Template Method Pattern)定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下重新定义算法中的某些步骤。

代码示例

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

    protected abstract void primitiveOperation1();
    protected abstract void primitiveOperation2();
}

public class ConcreteClass extends AbstractClass {
    protected void primitiveOperation1() {
        System.out.println("ConcreteClass Operation1");
    }

    protected void primitiveOperation2() {
        System.out.println("ConcreteClass Operation2");
    }
}

扩展

  • 讨论模板方法模式如何通过控制流程和延迟细节实现代码复用。
  • 分析模板方法模式的优缺点,尤其是在构建框架时的应用。
  • 提供在实际项目中的应用场景,如算法框架、测试框架等。

4.3 观察者模式

观察者模式(Observer Pattern)定义对象间的一对多依赖关系,使得每当一个对象改变状态时,其相关依赖对象都会收到通知并自动更新。

代码示例

public interface Observer {
    void update();
}

public class ConcreteObserver implements Observer {
    public void update() {
        System.out.println("Observer notified");
    }
}

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

    public void attach(Observer observer) {
        observers.add(observer);
    }

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

扩展

  • 讨论观察者模式如何实现对象之间的松耦合和事件驱动机制。
  • 分析观察者模式的优缺点,尤其是在处理复杂的依赖关系和通知机制时的优势。
  • 提供在实际项目中的应用场景,如事件监听器、发布-订阅系统等。

4.4 迭代器模式

迭代器模式(Iterator Pattern)提供一种方法顺序访问一个聚合对象中的各个元素,而不暴露该对象的内部表示。

代码示例

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

public class ConcreteIterator implements Iterator {
    private List<Object> list;
    private int position = 0;

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

    public boolean hasNext() {
        return position < list.size();
    }

    public Object next() {
        return list.get(position++);
    }
}

扩展

  • 讨论迭代器模式如何封装集合的遍历逻辑,解耦遍历行为与集合实现。
  • 分析迭代器模式的优缺点,尤其是在构建自定义集合类时的应用。
  • 提供在实际项目中的应用场景,如集合框架的设计、自定义遍历机制等。

4.5 责任链模式

责任链模式(Chain of Responsibility Pattern)为请求创建一个链式处理对象的机制,当请求沿着这条链传递时,每个处理对象都有机会处理该请求。

代码示例

public abstract class Handler {
    protected Handler successor;

    public void setSuccessor(Handler successor) {
        this.successor = successor;
    }

    public abstract void handleRequest(int request);
}

public class ConcreteHandler1 extends Handler {
    public void handleRequest(int request) {
        if (request < 10) {
            System.out.println("Handler1 handled request " + request);
        } else if (successor != null) {
            successor.handleRequest(request);
        }
    }
}

扩展

  • 讨论责任链模式如何通过将处理者链式组织,动态决定请求的处理方式。
  • 分析责任链模式的优缺点,尤其是在复杂请求处理流程中的应用。
  • 提供在实际项目中的应用场景,如权限验证、事件处理链等。

4.6 命令模式

命令模式(Command Pattern)将请求封装成对象,从而使得可以用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。

代码示例

public interface Command {
    void execute();
}

public class ConcreteCommand implements Command {
    private Receiver receiver;

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

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

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

扩展

  • 讨论命令模式如何封装请求,提高系统的可扩展性和灵活性。
  • 分析命令模式的优缺点,尤其是在实现可撤销操作和宏命令时的应用。
  • 提供在实际项目中的应用场景,如任务调度、事务管理等。

4.7 备忘录模式

备忘录模式(Memento Pattern)在不破坏封装性的前提下,捕获并保存一个对象的内部状态,以便将来恢复到该状态。

代码示例

public class Memento {
    private String state;

    public Memento(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }
}

public class Originator {
    private String state;

    public void setState(String state) {
        this.state = state;
    }

    public Memento saveStateToMemento() {
        return new Memento(state);
    }

    public void getStateFromMemento(Memento memento) {
        state = memento.getState();
    }
}

扩展

  • 讨论备忘录模式如何通过保存对象状态,实现撤销和恢复功能。
  • 分析备忘录模式的优缺点,尤其是在处理对象状态快照时的应用。
  • 提供在实际项目中的应用场景,如文本编辑器的撤销功能、游戏存档等。

4.8 状态模式

状态模式(State Pattern)允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。

代码示例

public interface State {
    void handle();
}

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

public class Context {
    private State state;

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

    public void request() {
        state.handle();
    }
}

扩展

  • 讨论状态模式如何通过将状态封装为对象,简化复杂状态转换逻辑。
  • 分析状态模式的优缺点,尤其是在处理多状态系统时的灵活性。
  • 提供在实际项目中的应用场景,如工作流管理、游戏状态机等。

4.9 中介者模式

中介者模式(Mediator Pattern)定义一个中介对象来封装一组对象的交互,使得这些对象不必显式地相互引用,从而使得它们的耦合松散,而且可以独立地改变它们之间的交互。

代码示例

public interface Mediator {
    void sendMessage(String message, Colleague colleague);
}

public abstract class Colleague {
    protected Mediator mediator;

    public Colleague(Mediator mediator) {
        this.mediator = mediator;
    }

    public abstract void receiveMessage(String message);
}

public class ConcreteColleague1 extends Colleague {
    public ConcreteColleague1(Mediator mediator) {
        super(mediator);
    }

    public void receiveMessage(String message) {
        System.out.println("Colleague1 received: " + message);
    }
}

扩展

  • 讨论中介者模式如何减少对象间的直接依赖,促进松耦合设计。
  • 分析中介者模式的优缺点,尤其是在复杂交互系统中的应用。
  • 提供在实际项目中的应用场景,如聊天室、航空管制系统等。

4.10 访问者模式

访问者模式(Visitor Pattern)表示一个作用于某对象结构中的各元素的操作。它使得可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

代码示例

public interface Visitor {
    void visit(Element element);
}

public interface Element {
    void accept(Visitor visitor);
}

public class ConcreteElement implements Element {
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}
``

`

**扩展**- 讨论访问者模式如何将数据结构和操作分离,增加操作的灵活性。
- 分析访问者模式的优缺点,尤其是在操作多样化的数据结构时的优势。
- 提供在实际项目中的应用场景,如编译器、报表生成等。

### 4.11 解释器模式

解释器模式(Interpreter Pattern)为语言创建解释器,为某个语言定义它的文法表示,并建立一个解释器来解释这个语言中的句子。

**代码示例**:

```java
public interface Expression {
    int interpret();
}

public class NumberExpression implements Expression {
    private int number;

    public NumberExpression(int number) {
        this.number = number;
    }

    public int interpret() {
        return number;
    }
}

public class AddExpression implements Expression {
    private Expression leftExpression;
    private Expression rightExpression;

    public AddExpression(Expression leftExpression, Expression rightExpression) {
        this.leftExpression = leftExpression;
        this.rightExpression = rightExpression;
    }

    public int interpret() {
        return leftExpression.interpret() + rightExpression.interpret();
    }
}

扩展

  • 讨论解释器模式如何通过定义语言文法,简化语言解释的实现。
  • 分析解释器模式的优缺点,尤其是在实现自定义语言和规则时的应用。
  • 提供在实际项目中的应用场景,如SQL解析器、表达式计算器等。

5. 设计模式的应用与实践

5.1 如何选择合适的设计模式

在选择设计模式时,应根据具体的项目需求和场景,评估不同设计模式的适用性。开发者需要综合考虑代码的复杂性、可扩展性、维护成本等因素,选择最合适的设计模式。

5.2 设计模式在项目中的实际应用

在实际项目中,设计模式通常不是单独使用的,而是多种模式的组合。例如,工厂模式和单例模式可以结合使用,以创建和管理全局共享的资源。通过对实际项目的案例分析,可以更好地理解设计模式的实际应用。

5.3 设计模式的最佳实践

遵循设计模式的最佳实践有助于编写更高效、更健壮的代码。开发者应了解设计模式的适用场景和注意事项,避免模式滥用或误用。同时,及时更新和重构代码,以应对变化的需求和技术挑战。

5.4 设计模式的误用与反模式

虽然设计模式是开发的良好实践,但不当的使用可能导致复杂度增加、性能下降等问题。了解常见的反模式(如过度设计、滥用单例)有助于避免设计陷阱,提高代码质量。

6. 设计模式的扩展与创新

6.1 现代开发中的新模式与新方法

随着软件开发的不断发展,新的设计模式和方法也在不断涌现。例如,微服务架构、事件驱动设计等新模式正在逐步被广泛采用,开发者应当关注这些新趋势,并将其融入到实际开发中。

6.2 设计模式的组合与变种

设计模式在实践中往往需要组合使用,甚至需要根据具体需求进行变种。例如,组合使用策略模式和状态模式,可以实现更复杂的行为控制。通过灵活组合和变种设计模式,可以更好地满足复杂的业务需求。

6.3 设计模式与面向对象设计原则的结合

设计模式与面向对象设计原则(如SOLID原则)有着密切的关系。通过将设计模式与这些原则结合,可以创建更高质量的软件架构,提升代码的可维护性和可扩展性。

7. 总结

7.1 设计模式的学习与深入研究

设计模式是软件开发中的重要工具,通过系统学习和实践,可以提升设计能力。开发者应不断积累经验,深入研究设计模式的应用场景和扩展方法,以应对复杂的软件设计挑战。

7.2 设计模式在团队开发中的作用

在团队开发中,设计模式可以作为一种通用的设计语言,促进团队成员之间的沟通与协作。通过统一的设计模式,团队可以提高开发效率,减少沟通成本,并且确保代码的一致性和质量。

7.3 设计模式的未来发展趋势

随着技术的不断进步,设计模式也在不断演进。未来的设计模式将更加关注分布式系统、云计算、人工智能等新领域的应用。开发者应当保持对新技术的敏感性,不断学习和应用新模式,以应对未来的软件设计挑战。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CopyLower

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值