【再探】设计模式— 工厂方法、单例及原型模式

news2024/10/7 20:31:12

 创建型设计模式是处理对象创建的设计模式,主要特点是“将对象的创建与业务代码分离”。一共有五种:工厂方法模式、单例模式、原型模式、抽象工厂模式及建造者模式。

1 单例模式

需求:

  1. 在整个系统中只需要一个实例。
  2. 管理共享资源,例如数据库连接、配置文件读取等,可以减少资源消耗,提高性能。

1.1 单例模式介绍

确保某个类只有一个实例,自行实例化并且向整个系统提供这个实例。

图 单例模式UML

饿汉模式

在程序启动时就进行对象的实例化,单例对象会在类被加载时创建。实现简单、线程安全。但是无法进行懒加载,会带来一定的系统开销。

懒汉模式

类加载时不会创建单例对象,而是等到真正需要的时候才创建。懒汉模式第一次调用时才初始化,避免了内存浪费,但是需要注意线程安全问题。

枚举

实现单例的最佳方法,自动支持序列化机制、防止多次实例化并且线程安全。

图 实现单例模式的方式

public class HungryModel {

    private HungryModel() {}

    private final static HungryModel instance = new HungryModel();

    public static HungryModel getInstance() {
        return instance;
    }
}
public class DoubleCheckLocking {

    private DoubleCheckLocking() {}

    private static DoubleCheckLocking instance = null;

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

    private IoDHSingleton() {}

    private static class Holder {
        static final IoDHSingleton instance = new IoDHSingleton();
    }

    public static IoDHSingleton getInstance() {
        return Holder.instance;
    }

}

1.1.1 优缺点

优点:确保一个类在系统中只有一个实例,节约系统资源,提高性能。

缺点:不符合单一职责原则。

2 原型模式

需求:

  1. 需要频繁创建属性近似的对象。
  2. 需要保持对象在某个时刻的状态。

2.1 原型模式介绍

通过一个已存在的对象克隆出多个一摸一样的对象。

图 原型模式UML

public class Address implements Cloneable{

    public Address() {}

    @Override
    public Address clone() throws CloneNotSupportedException {
        return (Address)super.clone();
    }

    @Override
    public String toString() {
        return "Address(" + Integer.toHexString(hashCode()) + ")";
    }
}

public class User implements Cloneable{

    private List<Address> addressList;

    public void setAddressList(List<Address> addressList) {
        this.addressList = addressList;
    }

    @Override
    public User clone() throws CloneNotSupportedException {
        User clone = (User)super.clone();
        if (addressList != null) {
            List<Address> newList = new ArrayList<>();
            for (Address address : addressList) {
                newList.add(address.clone());
            }
            clone.setAddressList(newList);
        }
        return clone;
    }

    public static void main(String[] args) throws CloneNotSupportedException {
        User user = new User();
        List<Address> addresses = new ArrayList<>();
        addresses.add(new Address());
        addresses.add(new Address());
        user.setAddressList(addresses);

        User clone = user.clone();
        System.out.println(user);
        System.out.println(clone);
    }

    @Override
    public String toString() {
        return "User(" + Integer.toHexString(hashCode()) +"){" +
                "addressList=" + addressList +
                '}';
    }
}

2.1.1 优缺点

优点:1)减少了代码量;2)可读性、可维护性好,耦合度减小。

缺点:2)不符合单一职责原则;2)不符合开闭原则。当对象添加新的属性时可能需要修改代码。

3 工厂方法模式

需求:

  1. 将对象创建与业务代码剥离。
  2. 让用户在不需要知道具体的类型情况下,创建符合的对象。
  3. 隐藏创建这个实例的创建细节。

3.1 工厂方法模式介绍

将对象的创建与自身的业务逻辑分离。定义一个有创建对象接口的工厂,把创建对应产品的细节封装在不同的工厂实现类中。每增加新的产品,只需增加该产品以及对应的工厂实现类。

图 工厂方法模式UML

public class Car {

    private String engine;

    protected Car(String engine) {
        this.engine = engine;
    }
}

public class BMWCar extends Car{
    public BMWCar(String engine) {
        super(engine);
    }
}

public class TeslaCar extends Car{
    public TeslaCar(String engine) {
        super(engine);
    }
}

 

public interface CarFactory {
    Car buildCar();
}

public class BMWCarFactory implements CarFactory{
    @Override
    public Car buildCar() {
        return new BMWCar("汽油发动机");
    }
}

public class TeslaCarFactory implements CarFactory{
    @Override
    public Car buildCar() {
        return new TeslaCar("电动发动机");
    }
}
public class CarShop {
    public static void main(String[] args) {
        CarFactory carFactory = new BMWCarFactory();
        carFactory.buildCar();

        carFactory = new TeslaCarFactory();
        carFactory.buildCar();
    }
}

3.1.1 优缺点

优点:1)符合单一职责原则,可读性好。2)符合开闭原则,扩展性好。3)符合依赖倒置原则,耦合度降低。

缺点:类的数量增加,增加了系统的复杂性,可能会影响性能。

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

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

相关文章

看见游戏出海赛道的新机会

目前游戏出海的主要地区和国家都已经非常成熟&#xff0c;原有的发行方式方法也基本标配化&#xff0c;除了产品玩法的差异化&#xff0c;多元化渠道及获量新方式是提升竞争力的有效手段 4月24日&#xff0c;在深圳南山区&#xff0c;VERYCLOUD睿鸿股份与罗斯基、热力引擎共同主…

基于Spring Boot的外卖点餐系统设计与实现

基于Spring Boot的外卖点餐系统设计与实现 开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/idea 系统部分展示 网站首页界面图&#xff0c;通过进入网站可以查看首页、…

新时代教师口才演讲稿(3篇)

新时代教师口才演讲稿&#xff08;3篇&#xff09; 新时代教师口才演讲稿&#xff08;一&#xff09; 尊敬的各位领导、亲爱的同事们&#xff1a; 大家好&#xff01; 今天&#xff0c;我站在这里&#xff0c;深感荣幸与激动。在这个新时代里&#xff0c;教师的口才不仅仅是传…

后端java部署教程,docker配置解读(linux用docker部署新手入门)

文件夹结构 然后解读几个启动脚本 首先dockerFile # 使用anapsix/alpine-java:8_server-jre_unlimited作为基础镜像 FROM anapsix/alpine-java:8_server-jre_unlimited# 设置维护者信息 MAINTAINER adminxiaohuaikeji.com# 设置时区为Asia/Shanghai RUN ln -sf /usr/share/z…

组装nas的 神器 n100 ,改天组装一个!

N100的CPU性能虽然不是很强&#xff0c;性能接近4代i5移动端&#xff0c;但功耗很低&#xff0c;TDP只有6W&#xff0c;而且有个24单元的核显&#xff0c;解码视频能力不差。N100和Intel的i系列CPU是不同厂商生产的&#xff0c;并且它们的设计和架构也有所不同&#xff0c;因此…

Vitis HLS 学习笔记--Schedule Viewer 调度查看器

目录 1. 简介 2. Schedule Viewer详解 2.1 视图说明 2.1.1 Operation\Control Step 2.1.2 周期关系图 2.1.3 Schedule Viewer 菜单栏 2.1.4 属性视图 2.2 内容说明 2.2.1 实参&#xff08;b&#xff09;解释 2.2.2 实参&#xff08;a&#xff09;解释 2.2.3 变量&am…

# Windows 环境变量 Path 显示样式更改

Windows 环境变量 Path 显示样式更改 1、传统 Path 环境变量显示&#xff1a; ---》键盘上按【WIN I 】打开系统【设置】 ---》依次点击 ---》【系统】 ---》【系统信息】 ---》【高级系统设置】 ---》【高级】 ---》【环境变量】。或者依次点击&#xff1a; ---》右键 【我…

利用kimi等大模型进行运维参数解析和调优

在运维时&#xff0c;经常遇到很多参数&#xff0c;有些参数不知道意义&#xff0c;知道意义的也有些不知道合理参考值是多少。利用kimi等大模型来当老司机&#xff0c;轻松解决运维难题。 例如在运维hive参数时&#xff0c;有些不知道作用&#xff0c;提示次如下 你的角色是…

iOS上的UI是如何渲染出来的? 深入浅出UIKit渲染

我们在代码中写的View、Image等组件&#xff0c;最终是如何一步步渲染到屏幕上的呢&#xff1f;触摸、动画等是如何实现的&#xff1f;我们可以利用这些知识做哪些优化呢&#xff1f; 本文先从屏幕物理层原理出发&#xff0c;一步步介绍渲染流程&#xff0c;然后介绍iOS的UIKi…

go idea 不同区域的字体行距设置

1、代码区域的设置&#xff1a; 2、左侧project导航栏的设置&#xff1a; 3、问&#xff1a;go idea 底部的窗口&#xff0c;比如run、terminal、debug、version control等的设置&#xff1a;

pytorch 实现语义分割 PSPNet

语意分割是指一张图片上包含多个物体&#xff0c;通过语义分割可以识别物体分类、物体名称、像素识别的任务。和物体检测不同&#xff0c;他不会将物体框出来&#xff0c;而是根据像素的归属把物体标注出来。PSPNet 的输入是一张图片&#xff0c;例如300500&#xff0c;那么输出…

全志ARM-修改开发板内核启动日志

修改开发板内核日志输出级别&#xff1a; 默认输出级别为1&#xff0c;需要用超级用户权限修改 sudo vi /boot/orangepiEvn.txt 把第一行内核启动输出权限改为7&#xff0c;第二行把输出方式该为“serial”串口输出

QT:小项目:登录界面 (下一个连接数据库)

一、效果图 登录后&#xff1a; 二、项目工程结构 三、登录界面UI设计 四主界面 四、源码设计 login.h #ifndef LOGIN_H #define LOGIN_H#include <QDialog>namespace Ui { class login; }class login : public QDialog {Q_OBJECTpublic:explicit login(QWidge…

区块链技术下的DApp与电商:融合创新,开启商业新纪元

区块链技术的蓬勃发展正引领着一种新型应用程序的崛起——去中心化应用程序&#xff08;DApp&#xff09;。DApp并非传统的中心化应用&#xff0c;它构建于去中心化网络之上&#xff0c;融合了智能合约与前端用户界面&#xff0c;为用户提供了全新的交互体验。智能合约&#xf…

Leetcode—1146. 快照数组【中等】(ranges::lower_bound、std::prev函数)

2024每日刷题&#xff08;121&#xff09; Leetcode—1146. 快照数组 思路 题意很绕&#xff0c;解释一下&#xff1a; 拍一次照&#xff0c;复制出一个新数组&#xff0c;set 都在这个新的上面进行get 目标是得到第 id 个数组的特定位置的值 实现代码 class SnapshotArray…

ROS 2边学边练(39)-- 调试tf2

前言 这节还是围绕tf2来进行&#xff0c;只不过针对调试相关&#xff0c;把之前有过一面之缘的问题再次拿出来重点说明一下&#xff0c;此过程中我们会碰到之前几期中认识但还不怎么熟络的朋友比如tf2_echo、tf2_monitor、view_frames。 动动手 我们会利用一个有不少问题的例子…

Python-100-Days: Day06 Functions and Modules

函数的作用 编程大师Martin Fowler先生曾经说过&#xff1a;“代码有很多种坏味道&#xff0c;重复是最坏的一种&#xff01;”&#xff0c;要写出高质量的代码首先要解决的就是重复代码的问题。可以将特定的功能封装到一个称之为“函数”的功能模块中&#xff0c;在需要的时候…

JavaScript代码挑战#4

// 编程挑战 #4 /* 朱莉亚和凯特仍在研究狗&#xff0c;这次她们研究的是狗是否吃得太多或太少。 吃得太多意味着狗当前的食物份量比推荐份量大&#xff0c;吃得太少则相反。 吃得适量意味着狗当前的食物份量在推荐份量的正负 10% 的范围内&#xff08;参见提示&#xff09;。 …

企业邮箱哪个性价比高?2024年国内五大企业邮箱功能、价格对比

对于企业来说&#xff0c;更换企业邮箱的成本很高&#xff0c;包括企业邮箱数据迁移&#xff0c;新的通讯录导入等&#xff0c;都会耗时耗力。那么选择能稳定且性价比高的企业邮箱就至关重要&#xff0c;国内的Zoho Mail企业邮箱、网易企业邮箱、阿里企业邮箱、腾讯企业邮箱和新…

2024年宠物行业未来发展趋势(宠物行业增长风口深度报告)

近期&#xff0c;小红书联合第一财经发布了宠物行业洞察报告。报告中指出了宠物行业的三大消费新趋势&#xff1a;科学养宠、专宠专用和双向奔赴。而实际上&#xff0c;这三大趋势在2024年已经有明显的凸显。 趋势一&#xff1a;科学养宠 科学养宠主要体现在宠物主粮的选择上&…