当前位置: 首页 > article >正文

Java最常用的几种设计模式详解及适用业务场景

Java设计模式详解及适用业务场景

在软件开发中,设计模式是解决常见问题的最佳实践。通过采用这些设计模式,我们可以提高代码的可维护性、可读性和可扩展性。本文将介绍几种常见的Java设计模式,并结合具体代码示例,探讨它们适用的业务场景。

1. 单例模式(Singleton Pattern)
  • 定义:确保一个类只有一个实例,并提供一个全局访问点。
  • 优点:节约系统资源,提高系统性能;严格控制访问权限。
  • 应用场景:数据库连接池、日志记录器、配置管理器等需要全局唯一实例的场景。

代码示例

public class Singleton {
    // 创建一个静态的实例变量,并初始化为null
    private static Singleton instance = null;
    
    // 私有构造函数,防止外部实例化
    private Singleton() {}
    
    // 提供一个公共的静态方法,用于返回唯一的实例
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
    
    // 其他方法
    public void showMessage() {
        System.out.println("Hello World!");
    }
}
2. 工厂模式(Factory Pattern)
  • 定义:通过定义创建对象的接口,让子类决定实例化哪一个类。
  • 分类:包括简单工厂模式、工厂方法模式和抽象工厂模式。
  • 优点:增加程序的灵活性和可维护性;解耦对象的创建和使用

代码示例

// 产品接口
interface Shape {
    void draw();
}

// 具体产品类
class Circle implements Shape {
    public void draw() {
        System.out.println("Inside Circle::draw() method.");
    }
}

class Rectangle implements Shape {
    public void draw() {
        System.out.println("Inside Rectangle::draw() method.");
    }
}

// 工厂类
class ShapeFactory {
    // 使用getShape方法获取对象
    public Shape getShape(String shapeType) {
        if (shapeType == null) {
            return null;
        }
        if (shapeType.equalsIgnoreCase("CIRCLE")) {
            return new Circle();
        } else if (shapeType.equalsIgnoreCase("RECTANGLE")) {
            return new Rectangle();
        }
        return null;
    }
}

适用业务场景

  • 对象创建复杂:如涉及大量资源分配、复杂初始化逻辑或需要依赖注入的对象。
  • 解耦对象创建与具体实现:客户端代码无需知道对象如何创建,只需知道如何使用。
3. 观察者模式(Observer Pattern)
  • 定义:定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。当主题对象状态发生变化时,所有依赖它的观察者对象都会收到通知并自动更新。
  • 优点:实现松耦合,提高系统可维护性;支持广播通信。
  • 应用场景:GUI事件处理、发布-订阅系统、消息推送等。

代码示例

import java.util.ArrayList;
import java.util.List;

// 主题接口
interface Subject {
    void registerObserver(Observer o);
    void removeObserver(Observer o);
    void notifyObservers();
}

// 具体主题类
class ConcreteSubject implements Subject {
    private List<Observer> observers;
    private int state;

    public ConcreteSubject() {
        observers = new ArrayList<>();
    }

    public void registerObserver(Observer o) {
        observers.add(o);
    }

    public void removeObserver(Observer o) {
        observers.remove(o);
    }

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

    public int getState() {
        return state;
    }

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

// 观察者接口
interface Observer {
    void update(int state);
}

// 具体观察者类
class ConcreteObserver implements Observer {
    private String name;

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

    public void update(int state) {
        System.out.println("Observer " + name + " received state " + state);
    }
}

适用业务场景

  • 事件驱动系统:如GUI框架、消息队列系统等,当一个对象的状态改变时需要通知其他对象。
  • 实现发布/订阅模型:在内容管理系统、社交媒体平台等,用户可以订阅感兴趣的内容,并在内容更新时收到通知。
4. 策略模式(Strategy Pattern)
  • 定义:定义了一系列算法,将每一个算法封装起来,并使它们可以相互替换。
  • 优点:提高算法的扩展性和复用性;避免使用多重条件判断。
  • 应用场景:需要动态选择算法实现时,如排序算法、资源调度策略等。

代码示例

// 策略接口
interface Strategy {
    int doOperation(int num1, int num2);
}

// 具体策略类
class OperationAdd implements Strategy {
    public int doOperation(int num1, int num2) {
        return num1 + num2;
    }
}

class OperationSubtract implements Strategy {
    public int doOperation(int num1, int num2) {
        return num1 - num2;
    }
}

class OperationMultiply implements Strategy {
    public int doOperation(int num1, int num2) {
        return num1 * num2;
    }
}

// 上下文类
class Context {
    private Strategy strategy;

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

    public int executeStrategy(int num1, int num2) {
        return strategy.doOperation(num1, num2);
    }
}

适用业务场景

  • 算法选择:在需要根据不同条件选择不同的算法或行为时,如排序算法的选择。
  • 多条件分支处理:避免大量if-else语句,提高代码的可维护性和可读性。
5、适配器模式(Adapter Pattern)
  • 定义:将一个类的接口转换成客户希望的另外一个接口,使原本由于接口不兼容而不能一起工作的类可以一起工作。
  • 优点:提高代码的复用性;符合开闭原则。
  • 应用场景:需要使用现有的类,但类的接口不符合系统要求时。

代码示例

// 目标接口
public interface NewInterface {
    void newMethod();
}

// 源接口(老接口)
public class OldClass {
    public void oldMethod() {
        System.out.println("OldClass: 调用旧方法");
    }
}

// 适配器类
public class Adapter implements NewInterface {
    private final OldClass oldClass;

    public Adapter(OldClass oldClass) {
        this.oldClass = oldClass;
    }

    @Override
    public void newMethod() {
        oldClass.oldMethod();
    }
}

// 测试类
public class AdapterExample {
    public static void main(String[] args) {
        OldClass oldClass = new OldClass();
        NewInterface adapter = new Adapter(oldClass);
        adapter.newMethod(); // 调用新接口的方法,但实际调用的是旧接口的方法
    }
}
6、装饰器模式(Decorator Pattern)
  • 定义:动态地给一个对象添加一些额外的职责,就增加功能来说,装饰器模式比生成子类更为灵活。
  • 优点:提高代码的复用性和扩展性;符合开闭原则。
  • 应用场景:需要在不修改原有代码的情况下,为对象动态添加功能时。

代码示例

装饰器模式允许向一个现有的对象添加新的功能,同时不改变其结构。

// 组件接口
interface Component {
    void operation();
}

// 具体组件
class ConcreteComponent implements Component {
    @Override
    public void operation() {
        System.out.println("执行具体组件的操作");
    }
}

// 装饰器抽象类
abstract class Decorator implements Component {
    protected Component component;

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

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

// 具体装饰器 A
class ConcreteDecoratorA extends Decorator {
    public ConcreteDecoratorA(Component component) {
        super(component);
    }

    @Override
    public void operation() {
        super.operation();
        System.out.println("执行具体装饰器 A 的额外操作");
    }
}

// 具体装饰器 B
class ConcreteDecoratorB extends Decorator {
    public ConcreteDecoratorB(Component component) {
        super(component);
    }

    @Override
    public void operation() {
        super.operation();
        System.out.println("执行具体装饰器 B 的额外操作");
    }
}

// 测试类
public class DecoratorPatternExample {
    public static void main(String[] args) {
        Component component = new ConcreteComponent();
        Component decoratedComponentA = new ConcreteDecoratorA(component);
        Component decoratedComponentB = new ConcreteDecoratorB(decoratedComponentA);
        decoratedComponentB.operation();
    }
}
7、代理模式(Proxy Pattern)
  • 定义:为其他对象提供一种代理以控制对这个对象的访问。
  • 优点:实现远程代理、虚拟代理、保护代理等功能;隐藏对象的创建细节。
  • 应用场景:需要对访问进行控制、延迟加载、日志记录等场景。

代码示例

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

// 接口
interface UserService {
    void performAction();
}

// 实际服务类
class RealUserService implements UserService {
    @Override
    public void performAction() {
        System.out.println("执行实际操作");
    }
}

// 代理类
class UserServiceProxy implements UserService {
    private UserService realUserService;
    private String userRole;

    public UserServiceProxy(String userRole) {
        this.userRole = userRole;
    }

    @Override
    public void performAction() {
        if ("admin".equals(userRole)) {
            if (realUserService == null) {
                realUserService = new RealUserService();
            }
            realUserService.performAction();
        } else {
            System.out.println("您没有足够的权限执行此操作");
        }
    }

    public static void main(String[] args) {
        // 以管理员身份调用
        UserService adminProxy = new UserServiceProxy("admin");
        adminProxy.performAction();

        // 以普通用户身份调用
        UserService normalUserProxy = new UserServiceProxy("normal");
        normalUserProxy.performAction();
    }
}
8、 外观模式(Facade Pattern)
  • 定义:为子系统中的一组接口提供一个统一的接口,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
  • 优点:简化接口,降低客户端与子系统之间的耦合度;提高系统的易用性。
  • 应用场景:需要将复杂子系统的接口简化时。

代码示例

// 子系统A
class SubsystemA {
    public void operationA() {
        System.out.println("子系统A");
    }
}

// 子系统B
class SubsystemB {
    public void operationB() {
        System.out.println("子系统B");
    }
}

// 外观类
class Facade {
    private SubsystemA subsystemA;
    private SubsystemB subsystemB;

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

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

// 测试代码
public class FacadePatternExample {
    public static void main(String[] args) {
        Facade facade = new Facade();
        facade.operation();
    }
}
9、 模板方法模式(Template Method Pattern)
  • 定义:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中实现。
  • 优点:实现代码复用,提高系统灵活性;符合开闭原则。
  • 应用场景:需要在多个子类中实现相同的算法流程,但具体步骤有所差异时。

代码示例

// 抽象类
abstract class Coffee {
    // 模板方法:定义咖啡制作的流程
    public final void prepareCoffee() {
        boilWater();
        brewCoffee();
        pourInCup();
        addCondiments();
    }

    // 抽象方法:子类需要实现具体的制作步骤
    protected abstract void brewCoffee();

    // 钩子方法:子类可以选择覆盖或使用默认实现
    protected void addCondiments() {
        System.out.println("Adding condiments");
    }

    // 具体方法:共用的步骤
    private void boilWater() {
        System.out.println("Boiling water");
    }

    private void pourInCup() {
        System.out.println("Pouring into cup");
    }
}

// 具体子类:美式咖啡
class AmericanCoffee extends Coffee {
    @Override
    protected void brewCoffee() {
        System.out.println("Brewing American coffee");
    }
}

// 具体子类:拿铁咖啡
class LatteCoffee extends Coffee {
    @Override
    protected void brewCoffee() {
        System.out.println("Brewing Latte coffee");
    }

    @Override
    protected void addCondiments() {
        System.out.println("Adding milk and foam");
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Coffee coffee = new AmericanCoffee();
        coffee.prepareCoffee();
        
        coffee = new LatteCoffee();
        coffee.prepareCoffee();
    }
}

适用业务场景

  1. 支付处理系统:支付流程通常包括验证、记账和通知等步骤,但具体的实现可能因支付方式而异。模板方法模式允许定义一个算法的骨架,同时留下一些扩展点供子类实现。
  2. 图形界面应用程序:在GUI应用程序中,事件处理流程可能相似,但具体的响应可能不同。通过模板方法模式,可以定义一个事件处理的骨架,并在子类中实现具体的响应。
  3. 产品组装线:在制造工厂中,不同的产品可能需要不同的组装步骤,但总体流程是一致的。模板方法模式可以定义组装的骨架,并在子类中实现具体的组装步骤。

http://www.kler.cn/a/508042.html

相关文章:

  • 联通用户管理系统(一)
  • 【 MySQL 学习2】常用命令
  • 怎么用python写个唤醒睡眠电脑的脚本?
  • 如何在谷歌浏览器中设置自定义安全警告
  • Git 合并和 Git 变基有什么区别?
  • 用css和html制作太极图
  • 论文阅读:Structure-Driven Representation Learning for Deep Clustering
  • Vue2+OpenLayers实现折线绘制功能(提供Gitee源码)
  • MySQL 的mysql_secure_installation安全脚本执行过程介绍
  • jenkins-Job构建
  • 55.【5】BUUCTF WEB NCTF2019 sqli
  • 前端框架: Vue3组件设计模式
  • 【经典神经网络架构解析篇】【6】MobileNet网络详解:模型结构解析、创新点、代码实现
  • 重拾Python学习,先从把python删除开始。。。
  • 电子应用设计方案94:智能AI门禁系统设计
  • ubuntu下安装编译cmake,grpc与protobuf
  • 基于微信小程序的中国各地美食推荐平台的设计与实现springboot+论文源码调试讲解
  • 日拱一卒(20)——leetcode学习记录:大小为 K 且平均值大于等于阈值的子数组数目
  • Android wifi热点开关代码记录
  • 代码随想录算法训练营第三十五天-动态规划-01背包(一维)
  • 敏感信息数据搜集系统全英文
  • 【MySQL】表操作
  • C语言的语法糖
  • IvorySQL 4.2 发布
  • 25/1/17 嵌入式笔记 STM32F103
  • 利用.NET版Word处理控件Aspose.Words,使用 C# 在 Word 中创建图表