写点什么

工厂模式(三)泛型工厂的概念以及示例代码

用户头像
LSJ
关注
发布于: 2020 年 05 月 29 日

泛型工厂主要用于创建泛型实例。是一种更通用的范围更广的工厂方法 ;因为泛型工厂方法返回的不再是具有某个范围的对象,而是直接返回泛型对象或者是泛型的协变类型对象。不过话说回来,这种技术的使用场景在哪里,为什么要创建泛型对象?

Class对象



我们知道,在Java代码中是没法通过new T()这样的方式去创建泛型对象的 。部分原因是因为Java泛型中的类型擦除,而另一部分原因是编译器不能确定T具有默认构造函数。



为了解决这一问题,我们可以通过传递一个工厂对象,再使用该对象去创建实例。其实Java内部提供了一种便利的创建泛型实例的工厂对象,那就是Class对象(Class对象也可以称之为是一种类型标签),它可以对擦除进行补偿。



看下面代码:

class ClassTypeCapture<T> {
T x;
public ClassTypeCapture(Class<T> kind) {
x = kind.newInstance();
}
}



编译器会确保泛型参数可以匹配到Class标签上。有了Class的类型信息,就可以创建对象了。



在java9中 newInstance 方法已被标注为 @Deprecated



但是这么做有一个问题:类必须有默认构造函数,否则newInstance()函数在运行时会抛出异常,而这种错误并不会在编译器被捕获,显然这种方式并不友好。所以最好还是需要使用显式的工厂,并且限制其类型。



泛型工厂



首先定义一个 泛型工厂 接口,后面所有的具体工厂都实现此接口



interface Factory<T> {
T create();
}
class IntegerFactory implements Factory<Integer> {
publict Integer create() { return new Integer(0);}
}
class Widget {
public static class WidgetFactory implements Factory<Widget> {
public Widget create() { return new Widget(); }
}
}
class Foo<T> {
private T x;
public Foo(Factory<T> factory) {
x = factory.create();
}
}
class Boo {
public static void main() {
new Foo<Integer>(new IntegerFactory());
new Foo<Widget>(new Widget.Factory());
}
}



其实从上面代码可以看出,这只是传递Class<T>的一种变体,两种方式都传递工厂对象,但是后者在编译期能够得到检查



泛型工厂和普通工厂的本质套路还是相同的,仍然是一个工厂对应一个类 只不过在定义工厂接口时加上了类型参数,使得该工厂方法只能返回指定类型的对象。比如IntegerFactory只能创建Integer对象,WidgetFactory只能创建Widget对象。

然后Foo<T>类的构造函数将接受Factory<T>的工厂,编译器将确保create()方法返回T类型对象。



以上便是关于泛型工厂的简单示例,其中涉及到两种类型的泛型工厂

  1. 一个就是内置的Class对象

  2. 而另一个便是自定义的泛型工厂。



后续在写关于泛型工厂的使用实际使用场景。



发布于: 2020 年 05 月 29 日阅读数: 141
用户头像

LSJ

关注

微笑面对每一天 2018.11.11 加入

一个具有N年编程功力却早已拥有2N年工作经验的boy

评论

发布
暂无评论
工厂模式(三)泛型工厂的概念以及示例代码