首页 > 其他分享 >用静态工厂方法代替构造器

用静态工厂方法代替构造器

时间:2024-08-04 20:59:20浏览次数:10  
标签:materia String 静态 构造 代替 private public 驱动程序

静态工厂方法就是让类提供一个公用的静态工厂方法,根据该方法来返回一个实例对象

例如Boolean中的valueof方法:

public final class Boolean implements java.io.Serializable,
                                      Comparable<Boolean>
{
    /**
     * The {@code Boolean} object corresponding to the primitive
     * value {@code true}.
     */
    public static final Boolean TRUE = new Boolean(true);

    /**
     * The {@code Boolean} object corresponding to the primitive
     * value {@code false}.
     */
    public static final Boolean FALSE = new Boolean(false);

    public static Boolean valueOf(boolean b) {
        return (b ? TRUE : FALSE);
    }
}

 这跟传统的构造方法来创建对象有什么区别和优点呢?

1.与构造器不同,静态工厂方法有名称,能做到见名知意,使用起来更见方便,代码阅读性更好,而传统构造方法是以类名作为名称

public class materia {
    private String country;
    private String quality;
    private long price;

    private materia(String country, String quality) {
        this.country = country;
        this.quality = quality;
    }

    private materia(long price) {
        this.price = price;
    }

    //只关心他的来源和材质
    public static materia getCountryAndQuality(String country,String quality){
        return new materia("中国","银");
    }
    //只关心他的价格
    public static materia getPrice(long price ){
        return new materia(600);
    }

    public static void main(String[] args) {
        //传统创建方式
        materia steel = new materia("中国", "钢");
        materia silver = new materia(300);
        //静态工厂方法创建对象 代码可读性好
        materia steel1 = materia.getCountryAndQuality("中国", "钢"))
        materia silver2 = materia.getPrice(300);
    }
}

2.不用再每次调用的时候都创建一个新的意义相同的实例而产生资源浪费。静态工厂方法每次调用都返回的是同一个对象,这就使得不管什么时候,类都能严格控制存在哪些实例,可以确保一个类是Singleton或是不可实例化的,其次,可以实现一个不可变的值的类,保证不存在两个相同的实例

public class materia {
    private String country;
    private String quality;
    private long price;
    private static materia gold=new materia(700);
    private materia(long price) {
        this.price = price;
    }

    public static materia getGold(){
        System.out.println("创建金材料");
        return gold;
    }

    public static void main(String[] args) {
        materia gold1 = materia.getGold();
        materia gold2 = materia.getGold();
        System.out.println(gold1==gold2);//打印true
    }
}

其实这就是用静态工厂方法实现的单例模式 

3.静态工厂方法可以返回所声明的返回类型的任何子类型的对象:

public class materia {
    private String country;
    private long price;
    private String name;
    public materia(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public static materia getInstance(String name) {
        if (name.equalsIgnoreCase("gold")) {
            return new gold();
        } else if (name.equalsIgnoreCase("sliver")) {
            return new sliver();
        } else {
            return new materia(name);
        }
    }
    public static void main(String[] args) {
        materia materia1 = materia.getInstance("gold");
        System.out.println(materia1.getName());//打印gold
    }
}

4.静态工厂方法所返回对象的类可以输入的参数不同而改变:

EnumSet类没有公有的构造器,只有静态工厂方法,再OpenJD的实现中,根据底层枚举类型的元素数量,他们会返回两个子类之一的实例:如果元素数量小于或等于64,就像大多数枚举类型那样,静态工厂方法会返回一个RegularEnumSet实例,其底层是一个long类型的值,如果数量大于64,该工厂返回一个Ju'm'boEnumSet实例,其底层是一个数组。

这两个实现类的存在对客户端来说是不可见的。如何对于小型的枚举类型,RegularEnu'm'Set的性能优势不复存在,这个类就有可能再未来发行版中被删除,而这不会造成任何不良的影响,同样的,如果能提升性能,未来的发行版本中可能会添加Enum的第三个甚至第四个实现,客户端即不知道也不关心他们从这个静态工厂方法得到的对象的具体类,他们只关心一点,这类是EnumSet的某个子类。

5.静态工厂方法在编写包含该方法的类时,所返回对象的类并不一定存在:

(这里小编也没能理解,这是从网上摘抄的)

在JDBC(Java数据库连接)中的服务提供者框架是一个典型的例子,其中静态工厂方法可以返回对象的类在编写包含该方法的类时并不一定存在。

在JDBC中,服务提供者框架用于加载和管理数据库驱动程序。驱动程序供应商可以通过实现特定接口并提供驱动程序的实现来注册其驱动程序。服务提供者框架允许应用程序通过静态工厂方法获取适当的驱动程序实例,而无需显式引用特定的驱动程序类。

下面是一个简化的示例,展示了JDBC服务提供者框架的代码:

public class JDBCProviderFramework {
    // 私有构造函数,防止实例化
    private JDBCProviderFramework() {
    }
 
    // 静态工厂方法,返回数据库连接对象
    public static Connection getConnection(String url, String username, String password) throws SQLException {
        // 加载并注册合适的数据库驱动程序
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            throw new SQLException("Failed to load database driver");
        }
 
        // 获取数据库连接
        return DriverManager.getConnection(url, username, password);
    }
}
 
public class Main {
    public static void main(String[] args) {
        String url = "jdbc:mysql://localhost:3306/mydb";
        String username = "root";
        String password = "password";
 
        try {
            Connection connection = JDBCProviderFramework.getConnection(url, username, password);
            // 使用数据库连接执行操作
            // ...
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}


在上述示例中,JDBCProviderFramework 类是服务提供者框架的一部分。它包含一个私有构造函数和一个静态工厂方法 getConnection(),用于获取数据库连接对象。

在 getConnection() 方法中,首先使用 Class.forName() 方法加载并注册合适的数据库驱动程序,这里以MySQL驱动程序为例。然后,通过 DriverManager.getConnection() 方法获取数据库连接对象,并将其返回。

在 Main 类的 main() 方法中,我们使用 JDBCProviderFramework.getConnection() 方法获取数据库连接对象,并在实际应用程序中使用该连接对象执行数据库操作。

这里的关键是,在编写 JDBCProviderFramework 类时,并没有显式引用或依赖于特定的数据库驱动程序类。相反,通过使用服务提供者框架和静态工厂方法,可以在未来动态加载和使用不同的数据库驱动程序,而无需修改 JDBCProviderFramework 类的代码。

这种设计允许在未来定义或扩展返回的对象类(即不同的数据库驱动程序),以适应新的数据库技术或供应商。通过配置和动态加载,应用程序可以灵活地选择和切换不同的数据库驱动程序,而不需要修改主要的代码逻辑。

这个例子展示了静态工厂方法在JDBC服务提供者框架中的应用,其中返回的对象的类在编写包含该方法的类时并不一定存在,而是根据具体的实现在运行时动态加载和使用。

同样,提供静态工厂方法主要缺点就是如果没有公有的或受保护的构造器,就无法为这样的类创建子类。例如,集合框架的工具类都无法创建子类,不过也因祸得福,这样就鼓励程序员们使用组合而非继承,这真是不可变类型所必须的。

静态工厂方法程序员很难找到他们。

总之,静态工厂方法和构造器各有所长,一般来讲首选静态工厂,切记在没有考虑静态工厂方法是,要提供公有的构造方法。

标签:materia,String,静态,构造,代替,private,public,驱动程序
From: https://blog.csdn.net/Liulijie_/article/details/140895731

相关文章

  • JavaScript Proxy() 构造函数、Proxy对象
    Proxy()构造函数Proxy()构造函数用于创建Proxy对象。语法newProxy(target,handler)可以使用Proxy()构造函数来创建一个新的Proxy对象。构造函数接收两个必须的参数:target是要创建的对象,即要使用Proxy包装的目标对象(可以是任何类型的对象,包括原生数组,函数......
  • 静态路由的配置和实验
    简介:静态路由是一种需要管理员手工配置的特殊路由.静态路由比动态路由使用更少的带宽.并且不占用CPU资源来计算和更新路由.但是当网络发生故障或者拓扑发生变化后.静态路由不会自动更新.必须手动重新配置.静态路由有5个主要参数:目的地址和掩码.出接口和下一跳.优先级使用静态......
  • web部署时通过静态文件配置请求地址
    web部署动态更改请求地址通过访问根目录config配置实现在打包文件外部更改请求地址1.配置ViteexportdefaultdefineConfig({base:'/',//设置公共路径})2.创建配置文件开发:在根目录创建config.json文件不影响proxy代理{"apiBaseUrl":"/"}部署在d......
  • 【002】Linux配置静态ip地址
    一、环境虚拟机版本:VMwareLinux镜像文件:CentOS-7-x86_64-Minimal-2207-02.iso主机系统:Windows11家庭中文版主机系统类型:64位操作系统,基于x64的处理器远程连接工具:宝塔远程工具二、配置静态ip1、将虚拟机的网络模式设置为NAT模式2、设置VMware的网络模式选择VM......
  • C++实现静态链表
    #include<iostream>usingnamespacestd;//定义静态链表的最大容量constintMAX_SIZE=100;//节点类classNode{public:intdata;//节点存储的数据intnext;//节点指向下一个节点的索引(在数组中的位置)//默认构造函数Node():data(0......
  • C++ 面向对象基础-构造函数
    目录1.构造函数1.1基本使用1.2函数参数默认值1.3构造初始化列表 1.4隐式调用构造函数2.拷贝构造函数2.1概念2.2浅拷贝2.3深拷贝3.析构函数1.构造函数1.1基本使用构造函数是一种特殊的成员函数,用于创建对象时初始化,写法上有以下要求:●函数名称必......
  • ADC静态误差
    0前言图1表示测量数据精密度高,但准确度较差;图2 表示测量数据的准确度高,但精密度差;图3表示测量数据精密度和准确度都好,即精确度高。 1简介    模数转换器(ADC)广泛用于各种应用中,尤其是需要处理模拟传感器信号的测量系统,比如测量压力、流量、速度和温度。 ......
  • Windows图形界面(GUI)-MFC-C/C++ - 静态文本框(Static Text) - CStatic
    公开视频-> 链接点击跳转公开课程博客首页-> ​​​链接点击跳转博客主页目录静态文本框(StaticText)-CStatic基本概念成员函数示例代码静态文本框(StaticText)-CStatic基本概念静态文本框是一种用于显示文本的控件,用户不能编辑其中的文本。静态文本框......
  • 动态语言、静态语言、强类型语言、弱类型语言的区别
    我们在学习编程语言的类型系统时,经常听说“静态语言”“动态语言”“强类型语言”和“弱类型语言”这些概念,它们究竟是什么意思呢?各个概念之间又有什么区别呢?如果你阅读互联网上的博客,你也可能会发现一些矛盾的观点,有的作者糊涂地认为静态语言=强类型语言,或者动态语言=弱类型......
  • clion 《cmake自定义静态库后,生成的exe无法运行》
    背景项目生成lib引入,在生成exe过程中无法正常运行处理办法让链接器静态链接GCC和C++标准库set(CMAKE_EXE_LINKER_FLAGS"-static-libgcc-static-libstdc++")主CMakeLists.txtcmake_minimum_required(VERSION3.28)project(speech)#编译版本set(CMAKE_CXX_STANDAR......