带有工厂构造函数的抽象 class 的好处?
Benefits of an abstract class with a factory constructor?
我最近 运行 研究了一些示例,这些示例使用抽象 类 作为接口,但也向抽象接口添加了工厂构造函数,因此在某种意义上它可以是 "newed"向上。例如:
abstract class WidgetService {
factory WidgetService() = ConcreteWidgetService;
Widget getWidget();
void saveWidget(Widget widget);
}
class ConcreteWidgetService extends BaseWidgetService implements WidgetService {
WidgetService();
Widget getWidget() {
// code to get widget here
}
void saveWidget(Widget widget) {
// code to save widget here
}
}
此服务的用法将在其他一些服务或组件中使用,如下所示:
WidgetService _service = new WidgetService();
根据我对这个示例的理解,上面的行基本上"new" 了一个 WidgetService,它通常会从 Dart 分析器中产生一个警告,并且所说的服务变量实际上是一个基于 ConcreateWidgetService 的实例将 ConcreateWidgetService 分配给 WidgetService 的工厂构造函数。
这种方法有什么好处吗?根据我的 OOP 经验,当我不知道我将获得的具体类型时,我使用 abstract classes/interfaces 进行编程。在这里,我们似乎将具体类型立即分配给抽象工厂构造函数。我想我的第二个问题是在这种情况下为什么不直接在这里使用 ConcreteWidgetService 而不是重复所有方法签名?
在 Dart 中,所有 classes 也自动成为接口。创建一个 - 'newing up' - 一个 'interface' 的实例并没有什么奇怪的,因为它实际上只是创建一个 class.
的实例
一些抽象 classes 的目的是专门定义一个接口,但它们具有 return 一个 'default implementation' 自己的工厂构造函数。
例如:
void main() {
var v = new Map();
print(v.runtimeType);
}
打印:_InternalLinkedHashMap
- Map
.
的(当前)默认实现
核心库用户可以创建和使用 Map
的实例,而无需了解或关心他们实际获得的实现。库作者可以在不破坏任何人代码的情况下更改实现。
当然,其他 classes 也可以实现 Map
。
关于您的代码示例,WidgetService _service = new WidgetService();
不会产生分析器警告。请参阅此 example on DartPad(请注意,我修复了您示例中的几个错误)。
我最初对以下内容感到困惑:
factory WidgetService() = ConcreteWidgetService;
而不是:
factory WidgetService() => new ConcreteWidgetService();
但它似乎有效。
在您的示例中,好处是有限的,但在更复杂的情况下,好处会变得更加明显。
工厂构造函数允许您更好地控制构造函数 return 的内容。它可以 return 子类的实例或已经存在的(缓存的)实例。
它可以return基于构造函数参数的不同具体实现:
abstract class WidgetService {
WidgetService _cached;
factory WidgetService(String type) {
switch (type) {
case 'a':
return ConcreteWidgetServiceA();
case 'b':
return ConcreteWidgetServiceB();
default:
return _cached ??= DummyWidgetServiceA();
}
}
Widget getWidget();
void saveWidget(Widget widget);
}
您的示例似乎是为最终扩展到这种更灵活的方法做准备。
我最近 运行 研究了一些示例,这些示例使用抽象 类 作为接口,但也向抽象接口添加了工厂构造函数,因此在某种意义上它可以是 "newed"向上。例如:
abstract class WidgetService {
factory WidgetService() = ConcreteWidgetService;
Widget getWidget();
void saveWidget(Widget widget);
}
class ConcreteWidgetService extends BaseWidgetService implements WidgetService {
WidgetService();
Widget getWidget() {
// code to get widget here
}
void saveWidget(Widget widget) {
// code to save widget here
}
}
此服务的用法将在其他一些服务或组件中使用,如下所示:
WidgetService _service = new WidgetService();
根据我对这个示例的理解,上面的行基本上"new" 了一个 WidgetService,它通常会从 Dart 分析器中产生一个警告,并且所说的服务变量实际上是一个基于 ConcreateWidgetService 的实例将 ConcreateWidgetService 分配给 WidgetService 的工厂构造函数。
这种方法有什么好处吗?根据我的 OOP 经验,当我不知道我将获得的具体类型时,我使用 abstract classes/interfaces 进行编程。在这里,我们似乎将具体类型立即分配给抽象工厂构造函数。我想我的第二个问题是在这种情况下为什么不直接在这里使用 ConcreteWidgetService 而不是重复所有方法签名?
在 Dart 中,所有 classes 也自动成为接口。创建一个 - 'newing up' - 一个 'interface' 的实例并没有什么奇怪的,因为它实际上只是创建一个 class.
的实例一些抽象 classes 的目的是专门定义一个接口,但它们具有 return 一个 'default implementation' 自己的工厂构造函数。
例如:
void main() {
var v = new Map();
print(v.runtimeType);
}
打印:_InternalLinkedHashMap
- Map
.
核心库用户可以创建和使用 Map
的实例,而无需了解或关心他们实际获得的实现。库作者可以在不破坏任何人代码的情况下更改实现。
当然,其他 classes 也可以实现 Map
。
关于您的代码示例,WidgetService _service = new WidgetService();
不会产生分析器警告。请参阅此 example on DartPad(请注意,我修复了您示例中的几个错误)。
我最初对以下内容感到困惑:
factory WidgetService() = ConcreteWidgetService;
而不是:
factory WidgetService() => new ConcreteWidgetService();
但它似乎有效。
在您的示例中,好处是有限的,但在更复杂的情况下,好处会变得更加明显。
工厂构造函数允许您更好地控制构造函数 return 的内容。它可以 return 子类的实例或已经存在的(缓存的)实例。
它可以return基于构造函数参数的不同具体实现:
abstract class WidgetService {
WidgetService _cached;
factory WidgetService(String type) {
switch (type) {
case 'a':
return ConcreteWidgetServiceA();
case 'b':
return ConcreteWidgetServiceB();
default:
return _cached ??= DummyWidgetServiceA();
}
}
Widget getWidget();
void saveWidget(Widget widget);
}
您的示例似乎是为最终扩展到这种更灵活的方法做准备。