在项目中应用设计模式的实践指南

news2024/11/17 21:18:47

目录

✨✨ 祝屏幕前的您天天开心,每天都有好运相伴。我们一起加油!✨✨
🎈🎈作者主页: 喔的嘛呀🎈🎈

引言

一. 单例模式(Singleton Pattern)

1、实现单例模式的方式

1.1 懒汉式(Lazy Initialization)

1.2. 饿汉式(Eager Initialization)

1.3. 双重检查锁(Double-Checked Locking)

2、在项目中的应用

3、总结

二、 工厂模式(Factory Pattern)

1、工厂模式的实现方式

1.1简单工厂模式(Simple Factory Pattern)

1.2、工厂方法模式(Factory Method Pattern)

2、工厂模式在项目中的应用

3、总结

三. 观察者模式(Observer Pattern)

观察者模式的角色

观察者模式的优点

观察者模式的应用场景

示例代码

总结

四. 策略模式(Strategy Pattern)

策略模式的角色

策略模式的优点

策略模式的应用场景

示例代码

总结

结论


引言

设计模式是软件开发中的重要概念,它提供了一套经过验证的解决方案,可以帮助我们解决常见的设计问题。在项目中合理应用设计模式可以提高代码的质量和可维护性。本文将详细介绍如何在项目中应用设计模式,并提供具体的示例代码来说明。

一. 单例模式(Singleton Pattern)

单例模式用于确保一个类只有一个实例,并提供一个全局访问点。在项目中,单例模式通常用于管理共享资源或全局配置。

单例模式(Singleton Pattern)是一种创建型设计模式,用于确保一个类只有一个实例,并提供一个全局访问点。这种模式非常有用,特别是当一个类需要被多个不同的部分使用时,但我们希望这个类的实例始终保持一致性时。

1、实现单例模式的方式

1.1 懒汉式(Lazy Initialization)

在第一次被调用时才创建实例。

public class Singleton {
    private static Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}
1.2. 饿汉式(Eager Initialization)

在类加载时就创建实例。

public class Singleton {
    private static Singleton instance = new Singleton();

    private Singleton() {}

    public static Singleton getInstance() {
        return instance;
    }
}
1.3. 双重检查锁(Double-Checked Locking)

结合懒汉式和同步锁,在保证线程安全的同时减少同步开销。

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

2、在项目中的应用

在项目中,单例模式经常被用于以下情况:

  1. 日志记录器(Logger):一个应用可能需要一个全局的日志记录器来记录应用中的事件和错误信息。单例模式可以确保所有部分都使用相同的日志记录器实例。

  2. 配置管理器(Configuration Manager):一个应用可能需要一个全局的配置管理器来加载和保存配置信息。单例模式可以确保所有部分都使用相同的配置管理器实例。

  3. 数据库连接池(Database Connection Pool):在需要频繁访问数据库的应用中,可以使用单例模式管理数据库连接池,以避免频繁地创建和销毁连接。

  4. 线程池(Thread Pool):在需要管理多个线程的应用中,可以使用单例模式管理线程池,以便统一管理线程的创建和销毁。

  5. 缓存管理器(Cache Manager):在需要缓存数据的应用中,可以使用单例模式管理缓存,以便统一管理缓存的读写操作。

  6. GUI组件管理器(GUI Component Manager):在需要管理用户界面组件的应用中,可以使用单例模式管理界面组件,以确保所有部分都使用相同的界面组件实例。

以上是单例模式在项目中的一些常见应用场景。在实际项目中,可以根据具体需求和场景来灵活应用单例模式,以提高代码的质量和可维护性。

3、总结

单例模式是一种简单但非常有用的设计模式,在项目中经常被使用。然而,需要注意在多线程环境下保证线程安全,以及避免对单例实例进行破坏性操作(如反序列化)。

二、 工厂模式(Factory Pattern)

工厂模式是一种创建型设计模式,用于创建对象,但将对象的创建逻辑封装在工厂类中,从而实现解耦。工厂模式可以根据不同的条件来创建不同类型的对象,而客户端代码只需要知道如何使用工厂类来获取对象,而不需要知道具体对象的创建细节。

1、工厂模式的实现方式

1.1简单工厂模式(Simple Factory Pattern)

public interface Shape {
    void draw();
}

public class Circle implements Shape {
    @Override
    public void draw() {
        System.out.println("画一个圆形");
    }
}

public class Rectangle implements Shape {
    @Override
    public void draw() {
        System.out.println("画一个矩形");
    }
}

public class ShapeFactory {
    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;
    }
}

1.2、工厂方法模式(Factory Method Pattern)

public interface Shape {
    void draw();
}

public class Circle implements Shape {
    @Override
    public void draw() {
        System.out.println("画一个圆形");
    }
}

public class Rectangle implements Shape {
    @Override
    public void draw() {
        System.out.println("画一个矩形");
    }
}

public interface ShapeFactory {
    Shape createShape();
}

public class CircleFactory implements ShapeFactory {
    @Override
    public Shape createShape() {
        return new Circle();
    }
}

public class RectangleFactory implements ShapeFactory {
    @Override
    public Shape createShape() {
        return new Rectangle();
    }
}

2、工厂模式在项目中的应用

工厂模式在项目中的应用非常广泛,它主要用于创建对象,但将对象的创建逻辑封装在工厂类中,从而实现解耦。以下是工厂模式在项目中常见的应用场景和示例:

  1. 数据库连接工厂:在需要访问数据库的应用中,可以使用数据库连接工厂来创建数据库连接对象,根据不同的数据库类型返回不同的连接对象。
public interface Connection {
    void connect();
}

public class MySqlConnection implements Connection {
    @Override
    public void connect() {
        System.out.println("连接到MySQL数据库");
    }
}

public class OracleConnection implements Connection {
    @Override
    public void connect() {
        System.out.println("连接到Oracle数据库");
    }
}

public class ConnectionFactory {
    public static Connection getConnection(String dbType) {
        if ("mysql".equalsIgnoreCase(dbType)) {
            return new MySqlConnection();
        } else if ("oracle".equalsIgnoreCase(dbType)) {
            return new OracleConnection();
        }
        return null;
    }
}

日志记录器工厂:在需要记录日志的应用中,可以使用日志记录器工厂来创建日志记录器对象,根据不同的日志级别返回不同的日志记录器对象。

public interface Logger {
    void log(String message);
}

public class InfoLogger implements Logger {
    @Override
    public void log(String message) {
        System.out.println("[INFO] " + message);
    }
}

public class ErrorLogger implements Logger {
    @Override
    public void log(String message) {
        System.out.println("[ERROR] " + message);
    }
}

public class LoggerFactory {
    public static Logger getLogger(String logLevel) {
        if ("info".equalsIgnoreCase(logLevel)) {
            return new InfoLogger();
        } else if ("error".equalsIgnoreCase(logLevel)) {
            return new ErrorLogger();
        }
        return null;
    }
}

文件解析器工厂:在需要解析不同类型文件的应用中,可以使用文件解析器工厂来创建文件解析器对象,根据不同的文件类型返回不同的解析器对象。

public interface Parser {
    void parse(String filePath);
}

public class XmlParser implements Parser {
    @Override
    public void parse(String filePath) {
        System.out.println("解析XML文件:" + filePath);
    }
}

public class JsonParser implements Parser {
    @Override
    public void parse(String filePath) {
        System.out.println("解析JSON文件:" + filePath);
    }
}

public class ParserFactory {
    public static Parser getParser(String fileType) {
        if ("xml".equalsIgnoreCase(fileType)) {
            return new XmlParser();
        } else if ("json".equalsIgnoreCase(fileType)) {
            return new JsonParser();
        }
        return null;
    }
}

3、总结

工厂模式可以帮助我们在项目中实现对象的创建和管理,同时降低了类之间的耦合度,使得代码更加灵活和可维护。在实际项目中,根据具体需求和场景,可以灵活应用工厂模式来提高代码的质量和可扩展性。

三. 观察者模式(Observer Pattern)

观察者模式是一种行为设计模式,用于定义对象间的一对多依赖关系,当一个对象状态发生改变时,所有依赖于它的对象都会收到通知并自动更新。这种模式涉及到两种类型的对象:主题(Subject)和观察者(Observer)。主题维护一组观察者,提供注册和删除观察者的方法,并在状态变化时通知观察者。

观察者模式的角色

  1. Subject(主题):被观察的对象,它维护一组观察者,并提供注册和删除观察者的方法,以及通知观察者的方法。
  2. ConcreteSubject(具体主题):实现主题接口的具体对象,它存储主题的状态,当状态发生变化时通知所有观察者。
  3. Observer(观察者):定义一个更新接口用于接收并响应主题状态的变化。
  4. ConcreteObserver(具体观察者):实现观察者接口的具体对象,当接收到主题通知时执行特定的动作。

观察者模式的优点

  • 松耦合:主题和观察者之间是松耦合的,主题只知道观察者接口,而不需要了解具体的观察者实现。
  • 可扩展性:可以在运行时动态添加新的观察者。
  • 反应性:观察者能够立即对主题的状态变化做出响应。

观察者模式的应用场景

  • 当一个对象的改变需要同时改变其他对象,并且不知道具体有多少对象需要改变时,可以使用观察者模式。
  • 当一个抽象模型有两个方面,其中一个依赖于另一个,使用观察者模式可以将这两者封装在独立的对象中,使它们可以独立地改变和复用。

示例代码

以下是一个简单的观察者模式示例,模拟了一个简单的气象站发布天气信息的场景:

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

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

// 观察者接口
interface Observer {
    void update(float temperature, float humidity, float pressure);
}

// 具体主题
class WeatherData implements Subject {
    private List<Observer> observers;
    private float temperature;
    private float humidity;
    private float pressure;

    public WeatherData() {
        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() {
        for (Observer observer : observers) {
            observer.update(temperature, humidity, pressure);
        }
    }

    public void measurementsChanged() {
        notifyObservers();
    }

    public void setMeasurements(float temperature, float humidity, float pressure) {
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        measurementsChanged();
    }
}

// 具体观察者
class CurrentConditionsDisplay implements Observer {
    private float temperature;
    private float humidity;

    @Override
    public void update(float temperature, float humidity, float pressure) {
        this.temperature = temperature;
        this.humidity = humidity;
        display();
    }

    public void display() {
        System.out.println("Current conditions: " + temperature + "F degrees and " + humidity + "% humidity");
    }
}

public class WeatherStation {
    public static void main(String[] args) {
        WeatherData weatherData = new WeatherData();

        CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay();

        weatherData.registerObserver(currentDisplay);

        weatherData.setMeasurements(80, 65, 30.4f);
    }
}

在这个示例中,WeatherData 是具体主题,Display 是具体观察者。当气象站的温度发生变化时,会通知所有注册的观察者更新温度信息。

总结

观察者模式的优点包括降低耦合度、支持广播通信和扩展性好。在项目中,观察者模式常用于事件处理、消息通知和状态监控等场景。通过观察者模式,可以使系统的各个部分之间保持松散耦合,提高代码的灵活性和可维护性。

四. 策略模式(Strategy Pattern)

策略模式是一种行为设计模式,它定义了一系列算法,并将每个算法封装起来,使它们可以相互替换。策略模式可以让算法独立于使用它的客户端而变化,即客户端可以根据需要在运行时选择算法。在项目中,策略模式可以用于实现不同的算法或行为,使系统更灵活、可扩展和易于维护。

策略模式的角色

  1. Context(上下文):维护一个对策略对象的引用,在需要的时候调用策略对象的算法。
  2. Strategy(策略):定义所有支持的算法的公共接口,通常是一个接口或抽象类。
  3. ConcreteStrategy(具体策略):实现策略接口,提供具体的算法实现。

策略模式的优点

  • 算法独立性:可以在不影响客户端的情况下单独修改或替换算法。
  • 扩展性:易于增加新的算法或行为。
  • 复用性:可以将算法封装成独立的策略类,方便复用。

策略模式的应用场景

  • 当一个系统中有许多类只是在行为上有差别,可以使用策略模式来将这些行为封装到不同的策略类中,使得这些类可以方便地切换行为。
  • 当一个类的某个行为需要在运行时动态地选择时,可以使用策略模式。

示例代码

以下是一个简单的策略模式示例,模拟了一个电商系统根据不同的促销策略计算折扣价格的场景:

// 策略接口
interface DiscountStrategy {
    double applyDiscount(double amount);
}

// 具体策略:打折策略
class PercentageDiscountStrategy implements DiscountStrategy {
    private double percentage;

    public PercentageDiscountStrategy(double percentage) {
        this.percentage = percentage;
    }

    @Override
    public double applyDiscount(double amount) {
        return amount * (1 - percentage);
    }
}

// 具体策略:满减策略
class FullReductionDiscountStrategy implements DiscountStrategy {
    private double full;
    private double reduction;

    public FullReductionDiscountStrategy(double full, double reduction) {
        this.full = full;
        this.reduction = reduction;
    }

    @Override
    public double applyDiscount(double amount) {
        return amount >= full ? amount - reduction : amount;
    }
}

// 上下文
class ShoppingCart {
    private DiscountStrategy discountStrategy;

    public void setDiscountStrategy(DiscountStrategy discountStrategy) {
        this.discountStrategy = discountStrategy;
    }

    public double checkout(double amount) {
        return discountStrategy.applyDiscount(amount);
    }
}

public class StrategyPatternExample {
    public static void main(String[] args) {
        ShoppingCart cart = new ShoppingCart();

        // 使用打折策略
        cart.setDiscountStrategy(new PercentageDiscountStrategy(0.1));
        double discountedPrice = cart.checkout(100);
        System.out.println("打折后价格:" + discountedPrice);

        // 使用满减策略
        cart.setDiscountStrategy(new FullReductionDiscountStrategy(200, 50));
        discountedPrice = cart.checkout(250);
        System.out.println("满减后价格:" + discountedPrice);
    }
}

在这个示例中,DiscountStrategy 是策略接口,PercentageDiscountStrategyFullReductionDiscountStrategy 是具体策略。ShoppingCart 类是上下文,根据不同的促销策略计算折扣价格。

总结

总的来说,策略模式可以让算法的变化独立于使用算法的客户端,使得系统更灵活、可扩展和易于维护。

结论

设计模式是软件开发中的重要概念,通过合理应用设计模式,可以提高代码的质量和可维护性。在项目中应用设计模式需要根据具体情况选择合适的模式,并遵循设计模式的原则和规范。希望本文能帮助读者更好地理解和应用设计模式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1467148.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

List集合之UML、特点、遍历方式、迭代器原理、泛型、装拆箱及ArrayList、LinkedList和Vector的区别

目录 ​编辑 一、什么是UML 二、集合框架 三、List集合 1.特点 2.遍历方式 3.删除 4.优化 四、迭代器原理 五、泛型 六、装拆箱 七、ArrayList、LinkedList和Vector的区别 ArrayList和Vector的区别 LinkedList和Vector的区别 一、什么是UML UML&#xff08;Unif…

20个改善编码的Python异常处理技巧,让你的代码更高效

异常处理是写好代码的一个重要的方面&#xff0c;虽然许多开发人员都熟悉基本的try-except块&#xff0c;但是有很多更深入的知识可以使异常处理更高效、更可读和更python化。所以本文将介绍关于Python异常的20个可以显著改善编码的Python异常处理技巧&#xff0c;这些技巧可以…

C/C++内存管理学习【new】

文章目录 一、C/C内存分布二、C语言中动态内存管理方式&#xff1a;malloc/calloc/realloc/free三、C内存管理方式3.1 new/delete操作内置类型3.2 new和delete操作自定义类型四、operator new与operator delete函数五、new和delete的实现原理5.1 内置类型 六、定位new表达式(pl…

天锐绿盾 | 文件数据\资料防泄漏软件 \ 自动智能透明加密保护

怎么防止公司办公终端文件数据资料外泄? 防止公司办公终端文件数据资料外泄是非常重要的&#xff0c;以下是一些有效的措施&#xff1a; 限制访问权限&#xff1a;根据员工的职责和需求&#xff0c;设定文件和数据资料的访问权限。确保只有授权人员才能访问敏感信息。 加密存…

2024图像处理分析与信息工程国际学术会议(IACIPIE2024)

2024图像处理分析与信息工程国际学术会议(IACIPIE2024) 会议简介 2024图像处理分析与信息工程国际学术会议&#xff08;IACIPIE2024&#xff09;将在中国长沙举行。 IACIPIE2024是一个年度会议&#xff0c;探讨图像处理分析和信息工程相关领域的发展和影响&#xff0c;旨在介…

数字孪生低代码平台盘点(一):厂家介绍

特别说明&#xff1a;本文根据网上资料搜集整理而成&#xff0c;排名不分先后&#xff0c;配图是为了更好地阅读体验&#xff0c;并非表明该图为该平台所生产。如有错误之处&#xff0c;请在评论区提出。 一、优锘ChartBuilder 优锘ChartBuilder是一款基于Web的数据可视化工具…

C++的vector容器->基本概念、构造函数、赋值操作、容量和大小、插入和删除、数据存取、互换容器、预留空间

#include<iostream> using namespace std; #include <vector> //vector容器构造 void printVector(vector<int>& v) { for (vector<int>::iterator it v.begin(); it ! v.end(); it) { cout << *it << " "…

挑战杯 基于卷积神经网络的乳腺癌分类 深度学习 医学图像

文章目录 1 前言2 前言3 数据集3.1 良性样本3.2 病变样本 4 开发环境5 代码实现5.1 实现流程5.2 部分代码实现5.2.1 导入库5.2.2 图像加载5.2.3 标记5.2.4 分组5.2.5 构建模型训练 6 分析指标6.1 精度&#xff0c;召回率和F1度量6.2 混淆矩阵 7 结果和结论8 最后 1 前言 &…

RGB颜色如何转换为十六进制?16进制颜色代码怎么转为RGB颜色值?

我们在调整网站的色彩搭配&#xff0c;或修改图片的时候&#xff0c;偶尔需要用到RGB颜色值&#xff0c;或者16进制颜色代码。 如果我只知道16进制颜色代码想要知道RGB颜色值&#xff0c;那么16进制颜色代码怎么转为RGB颜色值&#xff1f;又或者我知道RGB颜色值想要知道16进制…

ubuntu使用LLVM官方发布的tar.xz来安装Clang编译器

ubuntu系统上的软件相比CentOS更新还是比较快的&#xff0c;但是还是难免有一些软件更新得不那么快&#xff0c;比如LLVM Clang编译器&#xff0c;目前ubuntu 22.04版本最高还只能安装LLVM 15&#xff0c;而LLVM 18 rc版本都出来了。参见https://github.com/llvm/llvm-project/…

Jenkins使用遇到的一些问题

一&#xff1a;插件依赖报错 比如遇到一堆插件报错&#xff0c;不是提示版本对不上&#xff0c;就是启用不了 这样直接把Jenkins升级就行了&#xff0c;比如我这个是命令行启动的&#xff0c;直接把他替换就好了 如果是遇到插件依赖报错&#xff0c;比如A插件异常 则点击这个插…

训练Sora模型,你可能需要这些开源代码,模型,数据集及算力评估

在之前的文章&#xff0c;我们总结了Sora模型上用到的一些核心技术和论文 复刻大模型 Sora 有多难&#xff1f;一张图带你读懂 Sora 的技术路径一文看懂大模型 Sora 技术推演 今天这篇文章来自我们社区讨论交流&#xff0c;我这边整理和总结现有的一些开源代码、模型、数据集…

网页数据的存储--存储为文本文件(TXT、JSON、CSV)

用解析器解析出数据后&#xff0c;接下来就是存储数据了。数据的存储有多种多样&#xff0c;其中最简单的一种是将数据直接保存为文本文件&#xff0c;如TXT、JSON、CSV等。这里就介绍将数据直接保存为文本文件。 目录 一、Python存储数据的方法 1、 文件读取 2、 文件写入…

milvus Delete api写s3的流程

Delete api写s3的流程 milvus版本:v2.3.2 整体架构: Delete 的数据流向 delete相关配置 dataNode:segment:insertBufSize: 16777216 # Max buffer size to flush for a single segment.deleteBufBytes: 67108864 # Max buffer size to flush del for a single channelsyncPe…

Neo4j导入数据之JAVA JDBC

目录结构 前言设置neo4j外部访问代码整理maven 依赖java 代码 参考链接 前言 公司需要获取neo4j数据库内容进行数据筛查&#xff0c;neo4j数据库咱也是头一次基础&#xff0c;辛辛苦苦安装好整理了安装neo4j的步骤&#xff0c;如今又遇到数据不知道怎么创建&#xff0c;关关难…

【wails】(4):使用wails做桌面应用开发,整合chatgpt-web项目做前端,进行本地开发,web端也可以连调,使用websocket实现

1&#xff0c;视频地址 【wails】&#xff08;4&#xff09;&#xff1a;使用wails做桌面应用开发&#xff0c;整合chatgpt-web项目做前端&#xff0c;进行本地开发&#xff0c;web端也可以连调&#xff0c;使用websocket实现 2&#xff0c;演示效果 启动先是报500 错误&#…

想设计智能手环,我需要设计哪种电路?

随着电子技术的高速发展&#xff0c;可穿戴设备逐渐火爆&#xff0c;其中之一是智能手环&#xff0c;作为现代可穿戴技术的热门产品之一&#xff0c;它集成了多种功能&#xff0c;如健康检测、运动跟踪、通知提醒等&#xff0c;为了实现这些功能&#xff0c;需要用上哪些电路模…

蜂窝物联网咖WiFi认证解决方案

项目背景 随着目前网咖模式越来越流行&#xff0c;给网吧部署一套无缝漫游的WIFI网络势在必行。同时&#xff0c;网吧无线准入的验证码在客户机上面进行更新&#xff0c;以防周边的人员进行蹭网&#xff0c;损失网吧的外网带宽。 01 需求分析 1. 网吧服务区域全部覆盖无盲区…

免费的WP模板网站推荐

免费wordpress模板下载 高端大气上档次的免费wordpress主题&#xff0c;首页大图全屏显示经典风格的wordpress主题。 https://www.wpniu.com/themes/289.html wordpress免费企业主题 深蓝色经典实用的wordpress网站模板&#xff0c;用wordpress免费企业主题搭建网站。 http…

大模型+影像:智能手机“上春山”

这个春节假期&#xff0c;一首《上春山》火了。吃瓜群众热热闹闹学了一个假期的“春山学”&#xff0c;了解了抢占C位的各种技巧。 假期过去&#xff0c;开工大吉&#xff0c;手机行业开始抢占今年的C位。那么问题来了&#xff0c;今年智能手机最大的机会点在哪里&#xff1f;答…