`
yeluowuhen
  • 浏览: 155903 次
  • 性别: Icon_minigender_2
  • 来自: 北京
社区版块
存档分类
最新评论

静态工厂方法[Z]

阅读更多
ava面向对象编程-静态工厂方法
Java面向对象编程- 静态工厂方法


创建类的实例的最常见的方式是用new语句调用类的构造方法。在这种情况下,程序可以创建类的任意多个实例,每执行一条new语句,都会导致Java虚拟机的堆区中产生一个新的对象。假如类需要进一步封装创建自身实例的细节,并且控制自身实例的数目,那么可以提供静态工厂方法。

例如Class实例是Java虚拟机在加载一个类时自动创建的,程序无法用new语句创建 java.lang.Class类的实例,因为Class类没有提供public类型的构造方法。为了使程序能获得代表某个类的Class实例,在 Class类中提供了静态工厂方法forName(String name),它的使用方式如下:

Class c=Class.forName("Sample"); //返回代表Sample类的实例

静态工厂方法与用new语句调用的构造方法相比,有以下区别。

(1)构造方法的名字必须与类名相同。这一特性的优点是符合Java语言的规范,缺点是类的所有重载的构造方法的名字都相同,不能从名字上区分每个重载方法,容易引起混淆。

静态工厂方法的方法名可以是任意的,这一特性的优点是可以提高程序代码的可读性,在方法名中能体现与实例有关的信息。例如例程11-5的Gender类有两个静态工厂方法:getFemale()和getMale()。

例程11-5 Gender.java

public class Gender{

private String description;

private static final Gender female=new Gender("女");

private static final Gender male=new Gender("男");


private Gender(String description){this.description=description;}


public static Gender getFemale(){

return female;

}


public static Gender getMale(){

return male;

}

public String getDescription(){return description;}

}

这一特性的缺点是与其他的静态方法没有明显的区别,使用户难以识别类中到底哪些静态方法专门负责返回类的实例。为了减少这一缺点带来的负面影响,可以在为静态工厂方法命名时尽量遵守约定俗成的规范,当然这不是必需的。目前比较流行的规范是把静态工厂方法命名为 valueOf或者getInstance。

l valueOf:该方法返回的实例与它的参数具有同样的值,例如:

Integer a=Integer.valueOf(100); //返回取值为100的Integer对象

从上面代码可以看出,valueOf()方法能执行类型转换操作,在本例中,把int类型的基本数据转换为Integer对象。

l getInstance:返回的实例与参数匹配,例如:

//返回符合中国标准的日历

Calendar cal=Calendar.getInstance(Locale.CHINA);

(2)每次执行 new语句时,都会创建一个新的对象。而静态工厂方法每次被调用的时候,是否会创建一个新的对象完全取决于方法的实现。

(3)new语句只能创建当前类的实例,而静态工厂方法可以返回当前类的子类的实例,这一特性可以在创建松耦合的系统接口时发挥作用,参见本章11.3.5节(松耦合的系统接口)。

静态工厂方法最主要的特点是:每次被调用的时候,不一定要创建一个新的对象。利用这一特点,静态工厂方法可用来创建以下类的实例。

l 单例类:只有惟一的实例的类。

l 枚举类:实例的数量有限的类。

l 具有实例缓存的类:能把已经创建的实例暂且存放在缓存中的类。

l 具有实例缓存的不可变类:不可变类的实例一旦创建,其属性值就不会被改变。

在下面几节,将结合具体的例子,介绍静态工厂方法的用途。

11.3.1 单例(singleton)类
单例类是指仅有一个实例的类。在系统中具有惟一性的组件可作为单例类,这种类的实例通常会占用较多的内存,或者实例的初始化过程比较冗长,因此随意创建这些类的实例会影响系统的性能。


Tips

熟悉Struts和 Hibernate软件的读者会发现,Struts框架的ActionServlet类就是单例类,此外,Hibernate的 SessionFactory和Configuration类也是单例类。



例程11-6的GlobalConfig类就是个单例类,它用来存放软件系统的配置信息。这些配置信息本来存放在配置文件中,在GlobalConfig类的构造方法中会从配置文件中读取配置信息,并把它存放在properties属性中。

例程11-6 GlobalConfig.java

import java.io.InputStream;

import java.io.FileInputStream;

import java.io.IOException;

import java.util.Properties;


public class GlobalConfig {

private static final GlobalConfig INSTANCE=new GlobalConfig();

private Properties properties = new Properies();

private GlobalConfig(){

try{

//加载配置信息

InputStream in=getClass().getResourceAsStream("myapp.properties");

properties.load(in);

in.close();

}catch(IOException e){throw new RuntimeException("加载配置信息失败");}

}

public static GlobalConfig getInstance(){ //静态工厂方法

return INSTANCE;

}

public Properties getProperties() {

return properties;

}

}

实现单例类有两种方式:

(1)把构造方法定义为private类型,提供public static final类型的静态变量,该变量引用类的惟一的实例,例如:

public class GlobalConfig {

public static final GlobalConfig INSTANCE =new GlobalConfig();

private GlobalConfig() {…}



}

这种方式的优点是实现起来比较简捷,而且类的成员声明清楚地表明该类是单例类。

(2)把构造方法定义为private类型,提供public static类型的静态工厂方法,例如:

public class GlobalConfig {

private static final GlobalConfig INSTANCE =new GlobalConfig();

private GlobalConfig() {…

}

public static GlobalConfig getInstance(){return INSTANCE;}



}

这种方式的优点是可以更灵活地决定如何创建类的实例,在不改变GlobalConfig类的接口的前提下,可以修改静态工厂方法getInstance() 的实现方式,比如把单例类改为针对每个线程分配一个实例,参见例程11-7。

例程11-7 GlobalConfig.java

package uselocal;

public class GlobalConfig {

private static final ThreadLocal<GlobalConfig> threadConfig=

new ThreadLocal<GlobalConfig>();

private Properties properties = null;

private GlobalConfig(){…}


public static GlobalConfig getInstance(){

GlobalConfig config=threadConfig.get();

if(config==null){

config=new GlobalConfig();

threadConfig.set(config);

}

return config;

}

public Properties getProperties() {return properties; }

}

以上程序用到了ThreadLocal类,关于它的用法参见第13章的13.14节(ThreadLocal类)。
分享到:
评论

相关推荐

    WorkFlow.7z

    在C++这样的静态类型语言中,反射并不像动态类型语言(如Java或Python)那样内建支持,但可以通过自定义实现来模拟。这个"WorkFlow.7z"压缩包包含的源代码似乎就是一种实现C++反射机制的尝试,特别是与Qt框架结合...

    IOS简单工厂模式实例

    简单工厂模式是一种静态工厂方法的设计模式,它创建对象的过程是封装在一个静态方法中,这个方法根据输入参数或者条件来决定返回哪个类型的实例。它的核心在于将对象的创建与使用分离,使代码更易于理解和维护。 在...

    stm32f407zgt6

    此外,它支持4至26MHz的晶体振荡器,内部16MHz的工厂校准的RC振荡器(准确度为1%),以及用于实时时钟(RTC)的32kHz振荡器和带校准的内部32kHz RC振荡器。 STM32F407ZGT6支持多种低功耗模式,包括睡眠模式、停止...

    jdk-11.0.6_windows-x64_bin.exe.7z

    3. **静态工厂方法for Optional**:`Optional.empty()`被添加为一个静态工厂方法,简化了创建空Optional对象的过程。 4. **文本块(Text Blocks)**:这是Java 11引入的一种新的语法特性,用于更方便地处理多行字符...

    5-4 习题课z可复用与可维护构造技杯1

    故在Parkable 中使用静态工厂方法,new 操作改为: Parkable parkable = Parkable.create(plate, width); 5. 设计 Motor、Plane 类,实现 Parkable 接口。但是,Car、Motor、Plane 的共性 rep和方法是重复的,可以...

    filterproject.7z

    工厂类可能会有一个静态方法,如`createFilterChain(List&lt;String&gt; filterTypes)`,它根据传入的过滤器类型列表创建并返回一个过滤器链。 总之,“filterproject.7z”中的内容为我们提供了一个很好的学习和应用设计...

    day24-多线程-设计模式.7z

    2. **工厂方法模式**:工厂方法模式是简单工厂模式的进一步抽象和推广,它定义一个创建对象的接口,让子类决定实例化哪一个类。在多线程场景下,工厂方法模式可以让每个线程根据需要创建自己的对象,降低了线程间的...

    PHP面向对象程序设计之对象生成方法详解共4页.pdf.z

    静态方法属于类而不是类的实例,可以直接通过类名调用,无需创建对象。例如: ```php class Helper { public static function sayHello() { echo "你好!"; } } Helper::sayHello(); ``` 单例模式确保一个类...

    JS继承笔记.7z

    可以使用`Object.assign()`或类的静态方法实现。 10. Symbol-keyed prototypal继承: 使用ES6的Symbol作为键,可以创建不被常规方式遍历到的私有属性,提供了一种新的继承模式。 以上就是JavaScript继承的一些...

    c#设计模式及习题.7z

    3. **简单工厂**:用于创建对象的静态工厂方法,避免了在客户端代码中使用new关键字直接实例化对象,提高了代码的灵活性。 4. **工厂方法**:定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法让类...

    STM32F407ZGT6数据手册中英双语对照.pdf

    在存储方面,STM32F407ZGT6具有灵活的静态存储控制器,支持紧凑型闪存、静态随机存取存储器、随机存取存储器、或非门和与非门存储器等多种存储模式。此外,该芯片还具有512字节的动态口令存储器和64K字节的核心耦合...

    JAVA程序员必读.7z

    1. **基础语法**:Java是一种静态类型的强类型语言,它的语法结构清晰,易于学习。基础语法包括变量声明、数据类型(如基本类型和引用类型)、运算符、流程控制语句(如if-else,for,while,switch)以及方法定义等...

    Dart.7z的基础语法练习

    - Dart是静态类型的,有基本数据类型如int(整数)、double(浮点数)、bool(布尔值)、String(字符串)以及null。 - 类型推断也是Dart的一个特性,变量的类型可以根据初始值自动推断。 3. **控制流**: - ...

    hanmingcode.7z

    8. 软件设计模式:理解并应用常见的设计模式,如工厂模式、单例模式、观察者模式等。 为了充分利用"hanmingcode.7z"中的内容,首先需要使用7-Zip或类似的解压缩工具将其解压。然后,根据文件结构和内容,你可以阅读...

    jboss-logging-3.1.0.ga.jar.z

    在这个例子中,我们首先导入了`Logger`类,然后通过静态工厂方法获取了一个与当前类关联的Logger实例。在`myMethod()`方法中,我们分别使用`info`和`error`方法记录日志,其中`error`方法还捕获并记录了异常信息。 ...

    Java学习测试题,看你会多少(主要基础类)

    3. **静态工厂方法**:`getInstance()` 方法是获取 `Singleton` 实例的唯一途径。它检查 `instance` 是否已经初始化,如果没有,则创建一个新的 `Singleton` 实例并返回;如果已经存在,则直接返回已存在的实例。 4....

    STM32F407ZGT6-datasheet-pdf-www.findic.com.pdf

    此外,它还支持多种静态存储器控制器,能够控制诸如CompactFlash、SRAM、PSRAM、NOR和NAND类型的存储器。同时,这款微控制器还具备LCD并行接口,支持8080和6800模式,适合用在需要图形显示的应用中。 时钟、复位及...

    Java岗面试题库.7z

    - 工厂模式:简单工厂、工厂方法、抽象工厂。 - 代理模式:静态代理、动态代理(JDK动态代理、CGLIB动态代理)。 - 观察者模式(Observer)、装饰器模式(Decorator)、适配器模式(Adapter)等。 9. **框架应用...

    使用FLEX和Actionscript开发FLASH 游戏10-3

    `NewTiledBackground` 函数是静态工厂方法,用于创建新的 `TiledBackground` 实例。 `startupTiledBackground` 方法在游戏启动时被调用,用于设置背景的初始状态,包括设置Z轴顺序(通常背景位于最底层),定义背景...

Global site tag (gtag.js) - Google Analytics