Java设计模式大揭秘,细致剖析5种经典模式

public class SingletonClass {

    private static SingletonClass instance;

    private SingletonClass() {
        // 私有构造函数,防止外部实例化
    }

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

如下所示,当我们发送Postman请求时,控制器类和结果将是同一个实例:

@RestController
@RequestMapping("/api")
public class SingletonController  {

    private SingletonClass singletonClass;

    public SingletonController(SingletonClass singletonClass) {
        this.singletonClass = singletonClass;
    }

    @GetMapping("/singleton")
    public String getSingleton() {
        return "This is a singleton instance: " + singletonClass.toString();
    }

}

图片

当您想要确保类仅存在一个实例时(例如,由程序的不同部分共享的单个数据库对象),您应该使用单例设计模式。

2 工厂

工厂方法是一种创建型设计模式,它提供了一种在创建过程中无需指定其具体类即可创建产品对象的解决方案。

图片

以下是Java代码示例,

PaymentProcessor是定义处理付款的合同的接口。

public interface PaymentProcessor {

    void processPayment();
}

CreditCardPaymentProcessor和PaypalPaymentProcessor是实现PaymentProcessor接口的具体类。这些类为CreditCard和PayPal付款特定的processPayment()方法提供了实现。

@Service
public class CreditCardPaymentProcessor implements PaymentProcessor {

    @Override
    public void processPayment() {
        // 信用卡支付交易
    }
}

@Service
public class PaypalPaymentProcessor implements PaymentProcessor {

    @Override
    public void processPayment() {
        //  PayPal支付交易
    }
}

PaymentProcessorFactory是实现工厂设计模式的工厂类。该类负责根据给定的付款方式创建不同PaymentProcessor实现的实例。

@Component
public class PaymentProcessorFactory {

    private final CreditCardPaymentProcessor creditCardPaymentProcessor;
    private final PaypalPaymentProcessor paypalPaymentProcessor;


    public PaymentProcessorFactory(CreditCardPaymentProcessor creditCardPaymentProcessor,
                                   PaypalPaymentProcessor paypalPaymentProcessor) {
        this.creditCardPaymentProcessor = creditCardPaymentProcessor;
        this.paypalPaymentProcessor = paypalPaymentProcessor;
    }

    public PaymentProcessor createPaymentProcessor(String paymentMethod) {
        if (paymentMethod.equalsIgnoreCase("creditcard")) {
           return creditCardPaymentProcessor;
        } else if (paymentMethod.equalsIgnoreCase("paypal")) {
            return paypalPaymentProcessor;
        }
        throw new IllegalArgumentException("Invalid payment method: " + paymentMethod);
    }
}

入口点处理对/processPayment/{paymentMethod}的请求,并使用PaymentProcessorFactory根据提供的paymentMethod创建适当的付款处理器。这简化了代码并使添加新付款处理器变得容易。

图片

工厂方法是一种用于节省系统资源的设计模式,它通过重复使用现有对象而不是重复构建它们来实现这一目的。

3 抽象工厂

抽象工厂是一种创建型设计模式,它允许您生成相关对象系列,无需指定其具体类。

图片

以下是Java代码示例,

//工厂类
public interface ProductFactory {
    Product createProduct();
}

public class ProductAFactory implements ProductFactory{
    @Override
    public Product createProduct() {
        return new ProductA();
    }
}

public class ProductBFactory implements ProductFactory{
    @Override
    public Product createProduct() {
        return new ProductB();
    }
}
//产品类
public interface Product {

    String getName();
}

public class ProductA implements Product {

    @Override
    public String getName() {
        return "Product A";
    }
}

public class ProductB implements Product {

    @Override
    public String getName() {
        return "Product B";
    }
}

// 使用 ProductAFactory 创建产品 A
ProductFactory productAFactory = new ProductAFactory();
Product productA = productAFactory.createProduct();
System.out.println("Product A: " + productA.getName());

// 使用 ProductBFactory 创建产品 B
ProductFactory productBFactory = new ProductBFactory();
Product productB = productBFactory.createProduct();
System.out.println("Product B: " + productB.getName());

抽象工厂模式在处理不同组相关项目时非常有用,它可以避免代码依赖于这些项目的特定类型。您可能事先不知道这些类型,或者希望为将来添加更多类型留出空间。这样,您的代码可以更加灵活和可扩展。

4 Builder

Builder是一种创建型设计模式,它允许您以逐步构建的方式创建复杂的对象。通过使用Builder模式,您可以使用相同的构建代码来生成不同类型和表示形式的对象。这种灵活性使得对象的构建过程更加可控和可定制。

图片

以下是Java代码示例,

@Builder
@Getter
@Setter
public class Beer {

    //必填属性
    private String name;
    private double drinkSize;
    private double alcoholPercentage;
    private double price;

    // 其他属性
    private String brewery;            // 生产啤酒的酿酒厂
    private String countryOfOrigin;    // 啤酒原产国
    private String description;        // 对啤酒特点的简要描述
    private String packaging;          // 包装类型(瓶装、罐装、生啤等)
    private String servingTemperature; // 推荐的饮用温度
    private String foodPairing;        // 适合搭配该啤酒的食物

}
@RestController
@RequestMapping("/api/beers")
public class BeerController {

    @GetMapping("/basic")
    public String createStandardBeer() {
        Beer beer = Beer.builder()
                .name("Standard Beer")
                .drinkSize(500)
                .alcoholPercentage(5.0)
                .price(5.99)
                .build();

        return "Created beer: " + beer.getName() + 
                ", Drink Size: " + beer.getDrinkSize() +
                ", Alcohol Percentage: " + beer.getAlcoholPercentage() +
                ", Price: " + beer.getPrice();
    }

    @GetMapping("/premium")
    public String createPremiumBeer() {
        Beer beer = Beer.builder()
                .name("Sample Beer")
                .drinkSize(330)
                .alcoholPercentage(5.0)
                .price(10.99)
                .brewery("Crafty Brews")
                .countryOfOrigin("United States")
                .description("A refreshing lager with a smooth taste.")
                .packaging("Bottle")
                .servingTemperature("4-6°C")
                .foodPairing("Pairs well with grilled chicken and salads.")
                .build();

        return "Created beer: " + beer.getName() + 
                ", Drink Size: " + beer.getDrinkSize() +
                ", Alcohol Percentage: " + beer.getAlcoholPercentage() +
                ", Price: " + beer.getPrice() +
                ", Brewery: " + beer.getBrewery() +
                ", Country of Origin: " + beer.getCountryOfOrigin() +
                ", Description: " + beer.getDescription() +
                ", Packaging: " + beer.getPackaging() +
                ", Serving Temperature: " + beer.getServingTemperature() +
                ", Food Pairing: " + beer.getFoodPairing();
    }

}

图片

图片

优点

  • 减少构造函数中的参数数量并提供可读的方法调用。

  • 允许在完整状态下实例化对象。

  • 简化了不可变对象的构建过程。

缺点

  • 它会增加代码行数,但提供了设计灵活性和改进的代码可读性。

  • 需要为每种产品类型创建单独的ConcreteBuilder类。

5 原型

原型是一种创建型设计模式,它允许您复制现有对象,而不依赖于它们的具体类。

图片

以下是Java代码示例,

designpatterns
└── creational
    └── prototype
        ├── controller
        │   └── TreeController.java
        ├── model
        │   ├── Tree.java
        │   ├── PlasticTree.java
        │   └── PineTree.java
        └── PrototypeDemoApplication.java
//抽象类
@Getter
@Setter
public abstract class Tree implements Cloneable {
    private String type;

    public abstract void copy();

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

//具体类-松树
public class PineTree extends Tree {

    public PineTree() {
        setType("Pine Tree");
    }

    @Override
    public void copy() {
        //实现
    }
}

//具体类-塑料树
  public PlasticTree() {
        setType("Plastic Tree");
    }

    @Override
    public void copy() {
        //实现
    }
@RestController
@RequestMapping("/api/trees")
public class TreeController {

    @GetMapping("/plastic")
    public String createPlasticTree() {
        Tree plasticTree = new PlasticTree();
        return "Created: " + plasticTree.getType();
    }

    @GetMapping("/pine")
    public String createPineTree() {
        Tree pineTree = new PineTree();
        return "Created: " + pineTree.getType();
    }
}

图片

图片

当需要创建的新对象与现有对象仅存在轻微差异时,原型模式非常有用。通过提前设置具有正确设置的实例,我们可以在需要更多相似对象时进行复制,从而节省了创建对象的时间和资源。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【机器学习合集】深度学习模型优化方法最优化问题合集 ->(个人学习记录笔记)

文章目录 最优化1. 最优化目标1.1 凸函数&凹函数1.2 鞍点1.3 学习率 2. 常见的深度学习模型优化方法2.1 随机梯度下降法2.2 动量法(Momentum)2.3 Nesterov accelerated gradient法(NAG)2.4 Adagrad法2.5 Adadelta与Rmsprop法2.6 Adam法2.7 Adam算法的改进 3. SGD的改进算法…

共享购模式:重新定义电商购物体验

在当今的电商市场,消费者对购物体验的需求日益增长,他们不再满足于传统的电商模式。为此,共享购模式应运而生,这种创新模式将线下实体商业与线上虚拟商城相结合,为用户带来全新的购物体验。本文将详细讲解共享购模式的…

云游数智农业世界,体验北斗时空智能

今日,2023年中国国际农业机械展览会在武汉正式拉开帷幕,众多与会者云集,各类农机产品纷呈,盛况空前。 千寻位置作为国家北斗地基增强系统的建设与运营方,在中国国际农业机械展览会上亮相,以「北斗时空智能 …

二维码生成和解析工具包-zxing

目录 1、简介 2、做个例子 2.1 添加依赖 2.2 工具类 2.3 测试 3、总结 今天在看一个开源项目的时候发现一个工具类,一个简单的生成二维码的工具类,测试了下很是方便。 虽然在平常的开发中没有使用过,为了以后的场景做个备份 1、简介 …

性能测试工具:Jmeter介绍

JMeter是一个开源的Java应用程序,由Apache软件基金会开发和维护,可用于性能测试、压力测试、接口测试等。 1. 原理 JMeter的基本原理是模拟多用户并发访问应用程序,通过发送HTTP请求或其他协议请求,并测量响应时间、吞吐量、并发…

小程序如何设置自取规则

​在小程序中,自取规则是指当客户下单时选择无需配送的情况下,如何设置相关的计费方式、指定时段费用、免费金额、预定时间和起取金额。下面将详细介绍如何设置这些规则,以便更好地满足客户的需求。 在小程序管理员后台->配送设置->自…

python自动化测试(二):获取元素定位的基本方式

目录 一、前置代码 二、通过HTML元素ID的方式去进行元素定位 三、通过HTML元素的name属性进行元素定位 四、练习一:打开百度登录界面并输入数据后登录 五、通过HTML元素的类名来进行元素定位 六、通过链接的文本值方式进行元素定位 七、通过部分的链接文本值…

安卓端GB28181设备接入模块如何实现实时位置订阅(MobilePosition)

技术背景 实时位置(MobilePosition)订阅和上报,对GB28281设备接入终端尤其重要,如移动单兵设备、执法记录仪、智能安全帽、车载终端等,Android国标接入设备通过获取到实时经纬度信息,按照一定的间隔上报到…

Hadoop3教程(三十五):(生产调优篇)HDFS小文件优化与MR集群简单压测

文章目录 (168)HDFS小文件优化方法(169)MapReduce集群压测参考文献 (168)HDFS小文件优化方法 小文件的弊端,之前也讲过,一是大量占用NameNode的空间,二是会使得寻址速度…

【目标跟踪】多目标跟踪测距

文章目录 前言python代码(带注释)main.pysort.pykalman.pydistance.py 结语 前言 先放效果图。目标框内左上角,显示的是目标距离相机的纵向距离。目标横向距离、速度已求出,没在图片展示。这里不仅仅实现对目标检测框的跟踪&#…

ios上架上传构建版本的windows工具

ios上架的必要步骤,是将打包好的二进制ipa文件,上传到app store的构建版本里,苹果并没有提供上传构建版本的工具,这里我介绍下windows下上传构建版本的方案。 下面说下上传的基本步骤: 第一步,上传前要先…

2023年中国医疗器械供应链服务平台发展趋势分析:向国家高端化市场发力[图]

医疗器械供应链服务主要分为全流程供应链服务与院内SPD服务,同时全流程供应链服务主要分为市场、仓储物流与金融三大服务。在SPD数字化赋能下,大数据、云计算等技术支撑促进一站式数字化供应链业务协同平台,带动了整体医疗器械供应链服务的发…

Homeassistant docker配置

Homeassistant docker配置 【说明】本系列为自用教程,记录以便下次使用 【背景】一台J1900 4G64G的小主机,安装了OP系统,里面自带了Docker。为实现Homeassistant(简称HA)控制智能家居设备,进行如下配置。 【…

uni-app配置微信开发者工具

一、配置微信开发者工具路径 工具->设置->运行配置->小程序运行配置->微信开发者工具路径 二、微信开发者工具开启服务端口

SpringBoot依赖和代码分开打包

前言 在公司的项目中,一个SpringBoot工程可能就上百MB,这时候当线上网速不佳的时候,部署起来就十分的痛苦了。。经常等好久才能上传完毕,接下来我来教大家一个SpringBoot工程代码和依赖分开打包的方法。这种方法将依赖和代码分开…

AWS SAA-C03考试知识点整理

S3: 不用于数据库功能 分类: S3 Standard :以便频繁访问 S3 Standard-IA 或 S3 One Zone-IA : 不经常访问的数据 Glacier: 最低的成本归档数据 S3 Intelligent-Tiering智能分层 :存储具有不断变化或未知访问…

Linux虚拟网络设备—Veth Pair

veth是Virtual Ethernet Device的缩写,是一种成对出现的Linux虚拟网络接口设备。它最常用的功能是用于将不同的Linux network namespaces 命名空间网络连接起来,让二个namespaces之间可以进行通信。我们可以简单的把veth pair理解为用一根网线&#xff0…

使用Scala和Sttp库编写爬虫程序

以下是一个使用Scala和Sttp库编写的视频爬虫程序,该程序使用了proxy来获取IP。请注意,这个示例需要在上找到一个具体的视频链接,然后将其传递给crawlVideo函数。 import scala.util.{Failure, Success} import scala.concurrent.{Future, Ex…

TCP网络通信

TCP通信的 实现发1收1 package TCP1;//完成TCP通信的 实现发1收1import java.io.DataOutputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket;public class Client {public static void main(S…

数据结构之队列(源代码➕图解➕习题)

前言 在学过栈之后,会了解到栈的底层是根据顺序表或者链表来构建的,那么我们今天要学习的队列是否也是基于顺序表和链表呢?那我们直接进入正题吧! 1. 队列的概念(图解) 还是跟上节一样,依旧用图…