首页 > 其他分享 >设计模式--创建型模式

设计模式--创建型模式

时间:2022-11-21 12:15:12浏览次数:65  
标签:-- 创建 Builder private 工厂 对象 模式 设计模式

设计模式--创建型模式

创建型模式,共五种:

工厂方法模式(一个工厂类ReturnNew子类)、抽象工厂模式(一个厂一个子类)、单例模式(恶汉,懒汉)、建造者模式(组合)、原型模式(Cloneable浅接口,Serializable深接口)。

单例模式

1.单例模式
单例模式用来创建全局唯一的对象。一个类只允许创建一个对象(或者叫实例),那这个类就是一个单例类,这种设计模式就叫作单例模式。单例有几种经典的实现方式,它们分别是:饿汉式、懒汉式、双重检测、静态内部类、枚举。

public class Singleton {
    private static Singleton singleton = new Singleton();
    private Singleton(){}
    public static Singleton getInstance(){
        return singleton;
    }
}

public class SynchronizedSingleton {
    //一个静态的实例
    private static SynchronizedSingleton synchronizedSingleton;
    //私有化构造函数
    private SynchronizedSingleton(){}
    //给出一个公共的静态方法返回一个单一实例
    public static SynchronizedSingleton getInstance(){
        if (synchronizedSingleton == null) {
            synchronized (SynchronizedSingleton.class) {
                if (synchronizedSingleton == null) {
                    synchronizedSingleton = new SynchronizedSingleton();
                }
            }
        }
        return synchronizedSingleton;
    }
}

参考

  1. https://zhuanlan.zhihu.com/p/347111780 概念
  2. https://www.cnblogs.com/zuoxiaolong/p/pattern2.html 代码

工厂模式

工厂模式包括简单工厂、工厂方法、抽象工厂这3种细分模式。其中,简单工厂和工厂方法比较常用,抽象工厂的应用场景比较特殊,所以很少用到,不是我们学习的重点。

工厂模式用来创建不同但是相关类型的对象(继承同一父类或者接口的一组子类),由给定的参数来决定创建哪种类型的对象。实际上,如果创建对象的逻辑并不复杂,那我们直接通过new来创建对象就可以了,不需要使用工厂模式。当创建逻辑比较复杂,是一个“大工程”的时候,我们就考虑使用工厂模式,封装对象的创建过程,将对象的创建和使用相分离。

当每个对象的创建逻辑都比较简单的时候,我推荐使用简单工厂模式,将多个对象的创建逻辑放到一个工厂类中。当每个对象的创建逻辑都比较复杂的时候,为了避免设计一个过于庞大的工厂类,我们推荐使用工厂方法模式,将创建逻辑拆分得更细,每个对象的创建逻辑独立到各自的工厂类中。

详细点说,工厂模式的作用有下面4个,这也是判断要不要使用工厂模式最本质的参考标准。

封装变化:创建逻辑有可能变化,封装成工厂类之后,创建逻辑的变更对调用者透明。
代码复用:创建代码抽离到独立的工厂类之后可以复用。
隔离复杂性:封装复杂的创建逻辑,调用者无需了解如何创建对象。
控制复杂度:将创建代码抽离出来,让原本的函数或类职责更单一,代码更简洁。
除此之外,我们还讲了工厂模式一个非常经典的应用场景:依赖注入框架,比如Spring IOC、Google Guice,它用来集中创建、组装、管理对象,跟具体业务代码解耦,让程序员聚焦在业务代码的开发上。

举例:
JDBC API(即抽象的接口或类)
参考
参考

  1. https://zhuanlan.zhihu.com/p/347111780 概念
  2. https://www.cnblogs.com/zuoxiaolong/p/pattern5.html 代码

建造者模式

3.建造者模式
建造者模式用来创建复杂对象,可以通过设置不同的可选参数,“定制化”地创建不同的对象。建造者模式的原理和实现比较简单,重点是掌握应用场景,避免过度使用。

如果一个类中有很多属性,为了避免构造函数的参数列表过长,影响代码的可读性和易用性,我们可以通过构造函数配合set()方法来解决。但是,如果存在下面情况中的任意一种,我们就要考虑使用建造者模式了。

  • 我们把类的必填属性放到构造函数中,强制创建对象的时候就设置。如果必填的属性有很多,把这些必填属性都放到构造函数中设置,那构造函数就又会出现参数列表很长的问题。如果我们把必填属性通过set()方法设置,那校验这些必填属性是否已经填写的逻辑就无处安放了。
  • 如果类的属性之间有一定的依赖关系或者约束条件,我们继续使用构造函数配合set()方法的设计思路,那这些依赖关系或约束条件的校验逻辑就无处安放了。
  • 如果我们希望创建不可变对象,也就是说,对象在创建好之后,就不能再修改内部的属性值,要实现这个功能,我们就不能在类中暴露set()方法。构造函数配合set()方法来设置属性值的方式就不适用了。
如何实现
在Computer 中创建一个静态内部类 Builder,然后将Computer 中的参数都复制到Builder类中。
在Computer中创建一个private的构造函数,参数为Builder类型
在Builder中创建一个public的构造函数,参数为Computer中必填的那些参数,cpu 和ram。
在Builder中创建设置函数,对Computer中那些可选参数进行赋值,返回值为Builder类型的实例
在Builder中创建一个build()方法,在其中构建Computer的实例并返回

public class Computer {
    private final String cpu;//必须
    private final String ram;//必须
    private final int usbCount;//可选
    private final String keyboard;//可选
    private final String display;//可选

    private Computer(Builder builder){
        this.cpu=builder.cpu;
        this.ram=builder.ram;
        this.usbCount=builder.usbCount;
        this.keyboard=builder.keyboard;
        this.display=builder.display;
    }
    public static class Builder{
        private String cpu;//必须
        private String ram;//必须
        private int usbCount;//可选
        private String keyboard;//可选
        private String display;//可选

        public Builder(String cup,String ram){
            this.cpu=cup;
            this.ram=ram;
        }

        public Builder setUsbCount(int usbCount) {
            this.usbCount = usbCount;
            return this;
        }
        public Builder setKeyboard(String keyboard) {
            this.keyboard = keyboard;
            return this;
        }
        public Builder setDisplay(String display) {
            this.display = display;
            return this;
        }        
        public Computer build(){
            return new Computer(this);
        }
    }
  //省略getter方法
}
omputer computer=new Computer.Builder("因特尔","三星")
                .setDisplay("三星24寸")
                .setKeyboard("罗技")
                .setUsbCount(2)
                .build();

参考

  1. https://zhuanlan.zhihu.com/p/347111780 概念
  2. https://zhuanlan.zhihu.com/p/58093669 代码
  3. https://www.zhihu.com/column/c_1371780045040623617 代码

原型模式

4.原型模式
如果对象的创建成本比较大,而同一个类的不同对象之间差别不大(大部分字段都相同),在这种情况下,我们可以利用对已有对象(原型)进行复制(或者叫拷贝)的方式,来创建新对象,以达到节省创建时间的目的。这种基于原型来创建对象的方式就叫作原型模式。

原型模式有两种实现方法,深拷贝和浅拷贝。浅拷贝只会复制对象中基本数据类型数据和引用对象的内存地址,不会递归地复制引用对象,以及引用对象的引用对象……而深拷贝得到的是一份完完全全独立的对象。所以,深拷贝比起浅拷贝来说,更加耗时,更加耗内存空间。

如果要拷贝的对象是不可变对象,浅拷贝共享不可变对象是没问题的,但对于可变对象来说,浅拷贝得到的对象和原始对象会共享部分数据,就有可能出现数据被修改的风险,也就变得复杂多了。操作非常耗时的情况下,我们比较推荐使用浅拷贝,否则,没有充分的理由,不要为了一点点的性能提升而使用浅拷贝。

举例:

  1. JAVA中的任何类只要实现了Cloneable标识接口
  2. SpringBatch框架中stepBean

https://www.cnblogs.com/zuoxiaolong/p/pattern24.html

标签:--,创建,Builder,private,工厂,对象,模式,设计模式
From: https://www.cnblogs.com/starmoon1994/p/16880995.html

相关文章

  • 使用EasyCV Mask2Former轻松实现图像分割
    简介: EasyCV可以轻松预测图像的分割谱以及训练定制化的分割模型。本文主要介绍如何使用EasyCV实现实例分割、全景分割和语义分割,及相关算法思想。作者:贺弘谦言......
  • MySQL45讲笔记
    MySQL45https://funnylog.gitee.io/mysql45/原系列目录:01讲基础架构:一条SQL查询语句是如何执行的主要介绍MySQL分为Server层和存储引擎层两部分:Server层包括连接......
  • 虚拟机centos7上安装docker+jenkins
    虚拟机centos7上安装docker+jenkins学习某册子的CICD时,安装了docker和jenkins,记录的安装过程和中间碰到的问题。使用的虚拟机为ParallelsDesktop,配置为2核4G,系统为cento......
  • ShaderGraph之基础光照
    在ShaderGraph中如果想要自定义一个纹理输入,需要添加SampleTexture2D节点,输出到片元着色器的BaseColor节点。还需要自定义一个Texture2D属性,用于外部修改纹理。新建材......
  • 17.5 稀疏调拨的内存映射文件--《Windows核心编程》
    原文链接:https://www.likecs.com/show-306421749.html,原文中代码是C++MFC程序,更详细。本文是C语言测试代码。(1)稀疏文件(SparseFile)定义指的是文件中出现大量的0数据,这......
  • 笔记本主板烧了什么症状
    日常使用计算机的时候,有的用户可能就会遇到自己笔记本电脑出现了一些问题,不确定是不是主板损坏了。那么笔记本主板烧了什么症状呢?主板烧了可能会出现风扇转不显示、蓝屏、......
  • eslint插件屁事多,解决方案
    eslint插件会检测是否写了分号,写了分号就报错,那么我们就设置一个文件".prettierrc"文件在里面写"semi":false从而在格式化代码的时候自动将分号去掉;写"singleQuote"......
  • C#学习笔记
    目录Hello,world!基本语法经典实例标识符C#关键字数据类型值类型(Valuetypes)引用类型(Referencetypes)对象(Object)类型动态(Dynamic)类型字符串(String)类型指针类型(......
  • 迅为iTOP3568开发板Android11获取root权限关闭selinux
    本文档所需资料在网盘资料“iTOP-3568开发板\02_【iTOP-RK3568开发板】开发资料\06_Android系统开发配套资料\02_Android11获取root权限配套资料”目录下。本文档参......
  • WordPress编辑器支持一键粘贴
    ​如何做到ueditor批量上传word图片?1、前端引用代码<!DOCTYPE html PUBLIC "-//W3C//DTDXHTML1.0Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-......