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类)。
分享到:
相关推荐
在C++这样的静态类型语言中,反射并不像动态类型语言(如Java或Python)那样内建支持,但可以通过自定义实现来模拟。这个"WorkFlow.7z"压缩包包含的源代码似乎就是一种实现C++反射机制的尝试,特别是与Qt框架结合...
简单工厂模式是一种静态工厂方法的设计模式,它创建对象的过程是封装在一个静态方法中,这个方法根据输入参数或者条件来决定返回哪个类型的实例。它的核心在于将对象的创建与使用分离,使代码更易于理解和维护。 在...
此外,它支持4至26MHz的晶体振荡器,内部16MHz的工厂校准的RC振荡器(准确度为1%),以及用于实时时钟(RTC)的32kHz振荡器和带校准的内部32kHz RC振荡器。 STM32F407ZGT6支持多种低功耗模式,包括睡眠模式、停止...
3. **静态工厂方法for Optional**:`Optional.empty()`被添加为一个静态工厂方法,简化了创建空Optional对象的过程。 4. **文本块(Text Blocks)**:这是Java 11引入的一种新的语法特性,用于更方便地处理多行字符...
故在Parkable 中使用静态工厂方法,new 操作改为: Parkable parkable = Parkable.create(plate, width); 5. 设计 Motor、Plane 类,实现 Parkable 接口。但是,Car、Motor、Plane 的共性 rep和方法是重复的,可以...
工厂类可能会有一个静态方法,如`createFilterChain(List<String> filterTypes)`,它根据传入的过滤器类型列表创建并返回一个过滤器链。 总之,“filterproject.7z”中的内容为我们提供了一个很好的学习和应用设计...
2. **工厂方法模式**:工厂方法模式是简单工厂模式的进一步抽象和推广,它定义一个创建对象的接口,让子类决定实例化哪一个类。在多线程场景下,工厂方法模式可以让每个线程根据需要创建自己的对象,降低了线程间的...
静态方法属于类而不是类的实例,可以直接通过类名调用,无需创建对象。例如: ```php class Helper { public static function sayHello() { echo "你好!"; } } Helper::sayHello(); ``` 单例模式确保一个类...
可以使用`Object.assign()`或类的静态方法实现。 10. Symbol-keyed prototypal继承: 使用ES6的Symbol作为键,可以创建不被常规方式遍历到的私有属性,提供了一种新的继承模式。 以上就是JavaScript继承的一些...
3. **简单工厂**:用于创建对象的静态工厂方法,避免了在客户端代码中使用new关键字直接实例化对象,提高了代码的灵活性。 4. **工厂方法**:定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法让类...
在存储方面,STM32F407ZGT6具有灵活的静态存储控制器,支持紧凑型闪存、静态随机存取存储器、随机存取存储器、或非门和与非门存储器等多种存储模式。此外,该芯片还具有512字节的动态口令存储器和64K字节的核心耦合...
1. **基础语法**:Java是一种静态类型的强类型语言,它的语法结构清晰,易于学习。基础语法包括变量声明、数据类型(如基本类型和引用类型)、运算符、流程控制语句(如if-else,for,while,switch)以及方法定义等...
- Dart是静态类型的,有基本数据类型如int(整数)、double(浮点数)、bool(布尔值)、String(字符串)以及null。 - 类型推断也是Dart的一个特性,变量的类型可以根据初始值自动推断。 3. **控制流**: - ...
8. 软件设计模式:理解并应用常见的设计模式,如工厂模式、单例模式、观察者模式等。 为了充分利用"hanmingcode.7z"中的内容,首先需要使用7-Zip或类似的解压缩工具将其解压。然后,根据文件结构和内容,你可以阅读...
在这个例子中,我们首先导入了`Logger`类,然后通过静态工厂方法获取了一个与当前类关联的Logger实例。在`myMethod()`方法中,我们分别使用`info`和`error`方法记录日志,其中`error`方法还捕获并记录了异常信息。 ...
3. **静态工厂方法**:`getInstance()` 方法是获取 `Singleton` 实例的唯一途径。它检查 `instance` 是否已经初始化,如果没有,则创建一个新的 `Singleton` 实例并返回;如果已经存在,则直接返回已存在的实例。 4....
此外,它还支持多种静态存储器控制器,能够控制诸如CompactFlash、SRAM、PSRAM、NOR和NAND类型的存储器。同时,这款微控制器还具备LCD并行接口,支持8080和6800模式,适合用在需要图形显示的应用中。 时钟、复位及...
- 工厂模式:简单工厂、工厂方法、抽象工厂。 - 代理模式:静态代理、动态代理(JDK动态代理、CGLIB动态代理)。 - 观察者模式(Observer)、装饰器模式(Decorator)、适配器模式(Adapter)等。 9. **框架应用...
`NewTiledBackground` 函数是静态工厂方法,用于创建新的 `TiledBackground` 实例。 `startupTiledBackground` 方法在游戏启动时被调用,用于设置背景的初始状态,包括设置Z轴顺序(通常背景位于最底层),定义背景...