创建者模式

news2024/12/23 15:38:46

1.单例模式

  • 单例模式能够保证一个类只有一个实例,并且提供一个可以访问该实例的全局节点

  • 实现步骤

    • 类中添加一个私有静态成员变量用于保存单例实例
    • 声明一个公有静态构建方法用于获取单例实例
    • 在静态方法中实现"延迟初始化"。 该方法会在首次被调用时创建一个新对象, 并将其存储在静态成员变量中。 此后该方法每次被调用时都返回该实例
    • 将类的构造函数设为私有。 类的静态方法仍能调用构造函数, 但是其他对象不能调用
    • 检查客户端代码, 将对单例的构造函数的调用替换为对其静态构建方法的调用
  • 优点与缺点

    • 优点

      • 保证一个类只有一个实例
      • 首次请求单例对象时对其进行初始化
    • 缺点

      • 违反单一职责(保证一个类只能有一个实例,又提供可以访问该实例的全局节点)
      • 多线程环境下需要进行特殊处理, 避免多个线程多次创建单例对象
  • 实现方式

    // 1.懒汉式
    public class HungrySingleton {
        // 类的构造函数设为私有
        private HungrySingleton() {
        }
    
        // 方式一直接声明
    //    public static HungrySingleton hungrySingleton = new HungrySingleton();
        // 方式二通过静态代码块
        private static HungrySingleton hungrySingleton ;
        static {
            hungrySingleton = new HungrySingleton();
        }
        // 声明一个公有静态构建方法用于获取单例实例
        public static HungrySingleton getHungrySingleton(){
            return hungrySingleton;
        }
    }
    
    // 2.饿汉式
    public class LazySingleton {
        private LazySingleton() {
        }
        // volatile防止指令重排 多线程情况下 先分配地址然后再初始化导致获取的实例对象为null
        private static volatile LazySingleton lazySingleton;
    
        public static LazySingleton getLazySingleton() {
            // 双重检查机制
            if (lazySingleton == null) {
                  synchronized (LazySingleton.class){
                      if (lazySingleton == null){
                          lazySingleton = new LazySingleton();
                      }
                      return lazySingleton;
                  }
            }
            return lazySingleton;
        }
    }
    // 3.静态内部类
    public class StaticInnerClassSingleton {
        private StaticInnerClassSingleton() {}
    
        /*
            类里面所有的类变量的赋值动作和静态代码块组成的<clinit>方法
            多线程情况下只会有一个线程去执行<cinit>方法,其他线程被唤醒,不会再进入<clinit>()方法。也就是说同一个加载器下,一个类型只会初始化一次。
            因为有指令重排序也不会影响到其它线程
         */
        public static class SingletonHolder {
            private static final StaticInnerClassSingleton  singleton= new StaticInnerClassSingleton();
        }
    
        public static StaticInnerClassSingleton getStaticInnerClassSingleton(){
            return SingletonHolder.singleton;
        }
    }
    
    // 4.枚举方式
    public enum SingletonEnum {
        /*
            线程安全且只会装载一次、饿汉式、单例模式中唯一一种不会被破坏的单例实现模式
         */
        INSTANCE;
    }
    
  • 破坏单例模式

    • 序列化

      public class StaticInnerClassSingleton implements Serializable {
          private StaticInnerClassSingleton() {}
          
          public static class SingletonHolder {
              private static final StaticInnerClassSingleton  singleton= new StaticInnerClassSingleton();
          }
      
          public static StaticInnerClassSingleton getStaticInnerClassSingleton(){
              return SingletonHolder.singleton;
          }
      
          // 当进行反序列化时,会自动调用该方法,将该方式的返回值直接返回 具体可以追踪源码
          public Object readResolver(){
              return SingletonHolder.singleton
          }
      }
      
    • 反射

      public class StaticInnerClassSingleton implements Serializable {
          private static boolean flag = false;
          // 解决反射破坏单例模式
          private StaticInnerClassSingleton() {
              synchronized (StaticInnerClassSingleton.class){
                  if (flag){
                      throw new RuntimeException("不能创建多个对象");
                  }
                  flag = true;
              }
          }
      
          public static class SingletonHolder {
              private static final StaticInnerClassSingleton  singleton= new StaticInnerClassSingleton();
          }
      
          public static StaticInnerClassSingleton getStaticInnerClassSingleton(){
              return SingletonHolder.singleton;
          }
      }
      

2.工厂方法模式

  • 定义用于创建对象的接口,让子类决定实例化哪个产品类对象。工厂方法使一个产品类的实例化延迟到其工厂的子类
  • 结构
    • 抽象工厂:提供创建产品的接口,调用者通过它访问具体工厂的工厂方法来创建产品
    • 具体工厂:实现抽象工厂中的抽象方法,完成具体产品的创建
    • 抽象产品:定义了产品的规范,描述了产品的主要特性和功能
    • 具体产品:实现抽象产品角色所定义的接口,由具体工厂来创建

image-20230115135215545

  • 实现

    public abstract class Coffee {
    
        public abstract String getName();
    
        public void addMilk(){
            System.out.println("添加牛奶");
        }
    
        public void addSugar(){
            System.out.println("添加糖");
        }
    }
    
    public class LatteCoffee extends Coffee{
        @Override
        public String getName() {
            return "拿铁咖啡";
        }
    }
    
    public class AmericanCoffee extends Coffee{
        @Override
        public String getName() {
            return "美式咖啡";
        }
    }
    
    public interface CoffeeFactory {
        Coffee orderCoffee();
    }
    
    public class AmericanCoffeeFactory implements CoffeeFactory{
        @Override
        public Coffee orderCoffee() {
            return new AmericanCoffee();
        }
    }
    
    public class LatteCoffeeFactory implements CoffeeFactory{
        @Override
        public Coffee orderCoffee() {
            return new LatteCoffee();
        }
    }
    
    public class CoffeeStore {
    
        private CoffeeFactory factory;
    
        public void setFactory(CoffeeFactory factory){
            this.factory = factory;
        }
    
        public Coffee orderCoffee() {
           return factory.orderCoffee();
        }
    }
    
  • 优点与缺点

    • 优点
      • 避免创建者和具体产品之间的紧密耦合
      • 开闭原则。 无需更改现有客户端代码, 你就可以在程序中引入新的产品类型
    • 缺点
      • 应用工厂方法模式需要引入许多新的子类, 代码可能会因此变得更复杂(类爆炸)

3.抽象工厂模式

  • 是一种为访问类提供一个创建一组相关或互相依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同组的不同等级的厂品的模式结构。是工厂模式的升级版本,工厂模式只生产一个等级的产品,而抽象模式可生产多个等级的产品。

  • 结构

    • 抽象工厂:提供创建产品的接口,包含多个创建产品的方法,可以创建多个不同等级的产品
    • 具体工厂:实现抽象工厂中的多个抽象方法,完成具体产品的创建
    • 抽象产品:定义产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品
    • 具体产品:实现抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间是多对一多关系
  • 产品和等级的概念

    • 装饰风艺术的椅子和沙发和咖啡桌理解为产品(公司下一系列的产品)
    • 装饰风、维多利亚、现代的椅子可以理解为等级 (同属于椅子一类)

    image-20230115143501941

  • 实现

    image-20230115145639955

public abstract class Coffee {
    public abstract String getName();

    public void addMilk(){
        System.out.println("添加牛奶");
    }

    public void addSugar(){
        System.out.println("添加糖");
    }
}

public class AmericanCoffee extends Coffee {

    @Override
    public String getName() {
        return "美式咖啡";
    }
}

public class LatteCoffee extends Coffee{
    @Override
    public String getName() {
        return "拿铁咖啡";
    }
}

public abstract class Dessert {

    abstract void show();
}

public class MatchMousse extends Dessert{
    @Override
    void show() {
        System.out.println("抹茶慕斯");
    }
}

public class Tiramisu extends Dessert{

    @Override
    void show() {
        System.out.println("提拉米苏");
    }
}

public interface DessertFactory {

    Coffee createCoffee();

    Dessert createDessert();
}

public class AmericanDessertFactory implements DessertFactory{
    @Override
    public Coffee createCoffee() {
        return new AmericanCoffee();
    }

    @Override
    public Dessert createDessert() {
        return new Tiramisu();
    }
}

public class ItalyDessertFactory implements DessertFactory{
    @Override
    public Coffee createCoffee() {
        return new LatteCoffee();
    }

    @Override
    public Dessert createDessert() {
        return new MatchMousse();
    }
}
  • 优点与缺点

    • 优点

      • 确保同一工厂生成的产品相互匹配

      • 避免客户端和具体产品代码的耦合

      • 单一职责原则。 你可以将产品生成代码抽取到同一位置, 使得代码易于维护

      • 开闭原则。 向应用程序中引入新产品变体时, 你无需修改客户端代码

    • 缺点

      • 由于采用该模式需要向应用中引入众多接口和类, 代码可能会比之前更加复杂

4.原型模式

  • 用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型对象相同的新对象

  • 结构

    • 抽象原型类:规定了具体原型对象必须实现clone()方法

    • 具体原型类:实现抽象原型类的clone()方法,它是可被复制的对象

    • 访问类:使用具体原型类中的clone()方法来复制新的对象

      image-20230115162353640

  • 实现

    • 浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指的对象的内存地址
    • 深克隆:创建一个新对象,属性中引用的其它对象也会被克隆,不再指向原有对象地址
public class Citation implements Cloneable{

    private Student student;

    public Student getStudent() {
        return student;
    }

    public void setStudent(Student student) {
        this.student = student;
    }

    public Citation() {
        System.out.println("Citation构造器执行了");
    }

    @Override
    protected Citation clone() throws CloneNotSupportedException {
        System.out.println("执行浅克隆Citation");
        return (Citation) super.clone();
    }

    public void show (){
        System.out.println(student.getName()+"同学在ACM亚洲区域赛获得一等奖,特此表扬!");
    }
}

@Data
public class Student {
    private String name;
}


public class TestProtype {
    public static void main(String[] args) throws CloneNotSupportedException {
        Citation citation1 = new Citation();
        Student student = new Student();
        student.setName("浪浪山");
        citation1.setStudent(student);
        System.out.println("===========克隆=============");
        Citation citation2 = citation1.clone();
        citation2.getStudent().setName("林林");
        citation1.show();
        citation2.show();
    }
}

优点与缺点

  • 优点

    • 克隆对象, 无需与它们所属的具体类相耦合

    • 克隆预生成原型, 避免反复运行初始化代码

    • 更方便地生成复杂对象

    • 开闭原则。 向应用程序中引入新产品变体时, 你无需修改客户端代码

  • 缺点

    • 克隆包含循环引用的复杂对象可能会非常麻烦

5.建造者模式

  • 将复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示

  • 结构

    • 抽象建造者类:规定要实现的复杂对象的那些部分的创建,并不涉及具体的部件对象的创建
    • 具体建造者类:完成复杂产品的各个部件的具体创建方法。在构造过程完成后,提供产品的实例
    • 产品类:创建的复杂对象
    • 指挥者类:调用具体建造者来创建复杂对象的各个部分,在指导中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建

    image-20230115203715570

  • 实现

    @Data
    public class Bike {
        private String frame;
        private String seat;
    }
    
    public abstract class Builder {
        protected Bike bike = new Bike();
        // 构建车架
        abstract void buildFrame();
        // 构建座椅
        abstract void buildSeat();
    
        abstract Bike createBike();
    }
    
    public class MoBikeBuilder extends Builder {
        @Override
        void buildFrame() {
            bike.setFrame("摩拜车架");
        }
    
        @Override
        void buildSeat() {
            bike.setSeat("摩拜座椅");
        }
    
        @Override
        Bike createBike() {
            return bike;
        }
    }
    
    public class OfoBuilder extends Builder {
        @Override
        void buildFrame() {
            bike.setFrame("ofo车架");
        }
    
        @Override
        void buildSeat() {
            bike.setSeat("ofo座椅");
        }
    
        @Override
        Bike createBike() {
            return bike;
        }
    }
    
    public class Director {
        private Builder builder;
    
        public Director(Builder builder) {
            this.builder = builder;
        }
    
        public Bike construct() {
           builder.buildFrame();
           builder.buildSeat();
           return builder.createBike();
        }
    }
    
  • 优缺点

    • 优点
      • 步创建对象,暂缓创建步骤或递归运行创建步骤
      • 生成不同形式的产品时,可以复用相同的制造代码
      • 单一职责原则, 可以将复杂构造代码从产品的业务逻辑中分离出来
    • 缺点
      • 由于该模式需要新增多个类, 因此代码整体复杂程度会有所增加

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

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

相关文章

【云原生kubernetes】k8s中pod使用详解

一、前言 在之前k8s组件一篇中&#xff0c;我们谈到了pod这个组件&#xff0c;了解到pod是k8s中资源管理的最小单位&#xff0c;可以说Pod是整个k8s对外提供服务的最基础的个体&#xff0c;有必要对Pod做深入的学习和探究。 二、再看k8s架构图 为了加深对k8s中pod的理解&#x…

ARM PWM 定时器与实战

一、什么是定时器&#xff08;timer&#xff09; 1、定时器是 SoC 中常见外设 (1) 定时器与计数器。计数器是用来计数的&#xff08;每隔一个固定时间会计一个数&#xff09;&#xff1b;因为计数器的计数时间周期是固定的&#xff0c;因此到了一定时间只要用计数值计数时间周…

contex-m基于IAR工程从boot阶段引导app

目录 1.修改工程 2.修改代码 Boot代码 App代码 3.修改FM33LG04x.icf 4.修改IAR工程icf配置路径 5.修改FM33LG04X.icf链接文件 6.编译工程 7.查看map文件 8.调试程序 1.修改工程 本次调试的demo为《UART0 DMA发送_串口中断示例》&#xff0c;以下修改都是基于该工程&…

初始C语言 - 函数

C语言中函数的分类&#xff1a; 1.库函数:C语言自带的函数&#xff0c;包含大量频繁使用的功能 2.自定义函数:有些库函数没有的&#xff0c;需要程序员自己设计一、库函数通过MSDN、cplusplus.com、cppreference.com这些网站&#xff0c;查看学习函数的作用和用法在使用库函数时…

portswigger靶场中目录遍历

portswigger靶场中目录遍历1.Bp靶场介绍1.1.访问靶场1.2.注意事项2.目录变量漏洞2.1.文件路径遍历2.1.1.开启靶场2.1.2.点击详情2.1.3.抓包2.1.4.修改参数2.1.5.过关2.2.用绝对路径旁路阻止遍历序列2.2.1.开启靶场2.2.2.修改参数2.2.3.过关2.3.非递归地剥离遍历序列2.3.1.开启靶…

Windows下让Qt5 QCamera响应UVC摄像头硬件按钮拍图

QCamera相机类提供了一些基本的功能&#xff0c;包括拍照和录制功能&#xff08;Windows不支持录制视频&#xff09;&#xff0c;但也有很多接口是没有封装的&#xff0c;比如有些UVC摄像头有物理按键&#xff0c;可以进行拍图等操作&#xff0c;但是QCamera没法响应硬件按钮的…

通信原理与MATLAB(十五):码间干扰和无码间干扰条件

目录1.码间干扰2.无码间干扰条件2.1 时域条件2.2 频域条件3.满足无码间干扰条件的滤波器3.1 理想低通滤波器3.2 余弦滚降滤波器4.不同滚降系数的余弦滚降滤波器时频域图4.1 代码4.2 结果图5.理想低通滤波器和升余弦滚降滤波器(α1)对比1.码间干扰 如下图所示&#xff0c;码间干…

Vue 基础之侦听器

Vue 基础之侦听器描述侦听器侦听器的创建侦听器的应用选项immediate 选项deep 选项未使用 deep 选项使用 deep 选项侦听目标对象中的单个属性描述 项目描述IDEVScode操作系统Windows 10 专业版Vue.js2.6.12 侦听器 侦听器允许开发者对数据进行监视&#xff0c;并指定数据发生…

数据分析-深度学习 Pytorch Day4

一&#xff1a;概述当你想训练好一个神经网络时&#xff0c;你需要做好三件事情&#xff1a;一个合适的网络结构&#xff0c;一个合适的训练算法&#xff0c;一个合适的训练技巧&#xff1a;合适的网络结构&#xff1a;包括网络结构和激活函数&#xff0c;你可以选择更深的卷积…

打工人必学的法律知识(四)——《中华人民共和国劳动法》

中华人民共和国劳动法http://www.npc.gov.cn/npc/c30834/201901/ffad2d4ae4da4585a041abf66e74753c.shtml 目录 第一章 总  则 第二章 促进就业 第三章 劳动合同和集体合同 第四章 工作时间和休息休假 第五章 工  资 第六章 劳动安全卫生 第七章 女职工和未…

大数据技术之Hadoop(HDFS)——超详细

第1章 HDFS概述 1.1 HDFS产出背景及定义 1&#xff09;HDFS产生背景 随着数据量越来越大&#xff0c;在一个操作系统存不下所有的数据&#xff0c;那么就分配到更多的操作系统管理的磁盘中&#xff0c;但是不方便管理和维护&#xff0c;迫切需要一种系统来管理多台机器上的文…

误删照片音视频文件不要担心 几种方法解救慌乱的你 别再病急乱投医啦 [附软件]

误删照片音视频文件不要担心 几种方法解救慌乱的你 方法1&#xff1a;从手机相册中恢复手机删除的照片 这里以vivo手机为例,其他手机也是差不多的 相册->右上角三个点->设置->云空间 进入云存储空间 点击云盘->我的备份->就能看到你自动上传的照片 相册-&…

【Linux】共享内存

目录 一、共享内存 1.1 申请共享内存块 1.2 释放共享内存块 1.3 挂接共享内存 二、共享内存的使用 2.1 Server端与Client端 2.2 挂接与运行 三、共享内存总结 3.1 共享内存的特点 3.2 共享内存实现访问控制 一、共享内存 共享内存是最快的IPC形式。一旦这样的内存映…

xxl-job原理(版本2.3.1)

一、xxl-job架构图 1、调度中心 ​ 负责管理调度信息&#xff0c;按照调度配置发出调度请求&#xff0c;自身不承担业务代码。调度系统与任务解耦&#xff0c;提高了系统可用性和稳定性&#xff0c;同时调度系统性能不再受限于任务模块。 2、执行器 负责接收调度请求并执行任…

CSS注入 2.0

看过CSS注入1.0的朋友&#xff0c;不相信对CSS注入有了一个概念性的理解&#xff0c;在上一篇文章中我只是简单复现了一下波兰老哥的CSS注入过程&#xff0c;阐述了其大致原理。对于其中很大一部分技术细节&#xff0c;代码细节并未做深入的理解(当时我也看不懂&#xff0c;哈哈…

什么是分布式事务

上一篇文章已经讲完分布式了&#xff0c;那暖男说要讲分布式事务那就一定会讲&#xff0c;只是我估计大家没料到暖男这么快就肝好了吧&#xff1f; 事务想必大家并不陌生&#xff0c;至于什么是 ACID&#xff0c;也是老生常谈了。不过暖男为了保证文章的完整性确保所有人都听得…

uniapp-微信小程序分包操作步骤详解

1、在原来的pages的同级下新建一个目录&#xff1a;package1 &#xff08;名字自己随便起。想分几个包就建几个新目录。比如package2、package3……&#xff09; 结构是并列的&#xff1a; 2、把想要放进分包里去的模块都剪切在新目录里面去。 &#xff08;就是以前全都放在…

移动端 - 搜索组件(suggest篇)

这一篇博客是和 search-input篇 衔接的, 需要的可以看上文 移动端 - 搜索组件(search-list篇) 这里我们需要去封装这么一个组件 先说一下大致的方向: 1. 根据父组件传入的关键字数据发送请求获取后端数据, 进行模板渲染 2. 处理一些边界情况(后端返回数据为空, 初次加载数据…

《小猫猫大课堂》三轮3——字符函数和字符串函数及其模拟实现

宝子&#xff0c;你不点个赞吗&#xff1f;不评个论吗&#xff1f;不收个藏吗&#xff1f; 最后的最后&#xff0c;关注我&#xff0c;关注我&#xff0c;关注我&#xff0c;你会看到更多有趣的博客哦&#xff01;&#xff01;&#xff01; 喵喵喵&#xff0c;你对我真的很重…

C语言——自定义类型详解(结构体,联合体,枚举,位段)

专栏&#xff1a;C语言 个人主页&#xff1a;HaiFan. 专栏简介&#xff1a;本专栏主要更新一些C语言的基础知识&#xff0c;也会实现一些小游戏和通讯录&#xff0c;学时管理系统之类的&#xff0c;有兴趣的朋友可以关注一下。 结构体前言一、结构体1.结构体类型的声明2.结构体…