了解Factory构造函数代码示例-Dart [英] Understanding Factory constructor code example - Dart

查看:140
本文介绍了了解Factory构造函数代码示例-Dart的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对这里提到的工厂构造函数示例有些疑问(


解决方案

tl; dr 在不需要 想要返回类本身的 new 实例的情况下使用工厂。用例:




  • 构造函数很昂贵,因此,如果可能的话,您想返回一个现有实例,而不是创建一个新实例;

  • 您只想创建一个类的实例(单例模式);

  • 您只想返回一个子类实例而不是该类



说明



Dart类可能具有生成构造函数工厂构造函数。生成构造函数是始终返回该类新实例的函数。因此,它不使用 return 关键字。常见的生成构造函数的形式为:

  class Person {
字符串名称;
字符串国家;

//未命名的生成器
Person(this.name,this.country);
}
var p = Person( ...)//返回Person类的新实例

工厂构造函数的约束要比生成构造函数的约束宽松。工厂只需要返回与该类具有相同类型或实现其方法(即满足其接口)的实例。此可以是该类的新实例,但也可以是该类的现有实例或子类的新实例/现有实例(必须具有与父代相同的方法)。工厂可以使用控制流来确定要返回的对象,并且必须使用 return 关键字。为了使工厂返回新的类实例,它必须首先调用生成的构造函数。





在您的示例中,未命名的工厂构造函数首先读取从名为 _cache 的Map属性中获取(由于它是 Static ,因此存储在类级别,因此与任何实例变量)。如果实例变量已经存在,则将其返回。否则,将通过调用命名的生成构造函数 Logger._internal 来生成新实例。缓存此值,然后返回。因为生成构造函数仅采用 name 参数,所以 mute 属性将始终初始化为false,但可以更改使用默认的setter:

  var log = Logger( ...); 
log.mute = true;
log.log(...); //不会打印

术语 factory 暗示了工厂模式,这是关于允许构造函数根据提供的参数返回子类实例(而不是类实例)的全部内容。 Dart中此用例的一个很好的例子是抽象的HTML 元素类,它定义了数十个返回不同子类的命名工厂构造函数。例如, Element.div() Element.li()返回< div> ; < li> 元素。



在此缓存应用程序中,我发现工厂有点用词不当,因为它的目的是避免调用生成的构造函数,并且我认为现实世界中的工厂本质上是生成的。也许在这里更合适的术语是仓库:如果某件商品已经可用,请将其从货架上取下并交付。如果不是,请调用新的。



这与命名构造函数有何关系?生成器构造函数和工厂构造函数都可以不命名,也可以命名:

  ... 
//命名为生成器
//委托给默认的生成器
Person.greek(String name):this(name, Greece);

//名为factory
factory Person.greek(String name){
return Greek(name);
}
}

class希腊文扩展Person {
Greek(String name):super(name, Greece);
}



I have some niggling questions about factory constructors example mentioned here (https://www.dartlang.org/guides/language/language-tour#factory-constructors). I am aware of only three types of constructors on a basic level - default, named and parameterised.

  1. Why should I use factory at all for this example?
  2. Is that a named constructor which is being used? and why?

解决方案

tl;dr Use a factory in situations where you don't necessarily want to return a new instance of the class itself. Use cases:

  • the constructor is expensive, so you want to return an existing instance - if possible - instead of creating a new one;
  • you only ever want to create one instance of a class (the singleton pattern);
  • you want to return a subclass instance instead of the class itself.

Explanation

A Dart class may have generative constructors or factory constructors. A generative constructor is a function that always returns a new instance of the class. Because of this, it does not utilize the return keyword. A common generative constructor is of the form:

class Person {
  String name;
  String country;

  // unnamed generative constructor
  Person(this.name, this.country);
}
var p = Person("...") // returns a new instance of the Person class

A factory constructor has looser constraints than a generative constructor. The factory need only return an instance that is the same type as the class or that implements its methods (ie satisfies its interface). This could be a new instance of the class, but could also be an existing instance of the class or a new/existing instance of a subclass (which will necessarily have the same methods as the parent). A factory can use control flow to determine what object to return, and must utilize the return keyword. In order for a factory to return a new class instance, it must first call a generative constructor.

In your example, the unnamed factory constructor first reads from a Map property called _cache (which, because it is Static, is stored at the class level and therefore independent of any instance variable). If an instance variable already exists, it is returned. Otherwise, a new instance is generated by calling the named generative constructor Logger._internal. This value is cached and then returned. Because the generative constructor takes only a name parameter, the mute property will always be initialized to false, but can be changed with the default setter:

var log = Logger("...");
log.mute = true;
log.log(...); // will not print

The term factory alludes to the Factory Pattern, which is all about allowing a constructor to return a subclass instance (instead of a class instance) based on the arguments supplied. A good example of this use case in Dart is the abstract HTML Element class, which defines dozens of named factory constructor functions returning different subclasses. For example, Element.div() and Element.li() return <div> and <li> elements, respectively.

In this caching application, I find "factory" a bit of a misnomer since its purpose is to avoid calls to the generative constructor, and I think of real-world factories as inherently generative. Perhaps a more suitable term here would be "warehouse": if an item is already available, pull it off the shelf and deliver it. If not, call for a new one.

How does all this relate to named constructors? Generative and factory constructors can both be either unnamed or named:

...
  // named generative
  // delegates to the default generative constructor
  Person.greek(String name) : this(name, "Greece"); 

  // named factory 
  factory Person.greek(String name) {
    return Greek(name);
  }
}

class Greek extends Person {
  Greek(String name) : super(name, "Greece");
}


这篇关于了解Factory构造函数代码示例-Dart的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆