dart中factory关键词的使用

黄鹏宇 434 2021-10-19

title: dart中factory关键词的使用
date: 2020-05-10 13:26:43
tags: 学习

一. 官方的描述

Use the factory keyword when implementing a constructor that doesn’t always create a new instance of its class. For example, a factory constructor might return an instance from a cache, or it might return an instance of a subtype.
当你使用factory关键词时,你能控制在使用构造函数时,并不总是创建一个新的该类的对象,比如它可能会从缓存中返回一个已有的实例,或者是返回子类的实例。

二. 与构造函数的差别

构造函数不能有返回值,而factory必须有

三. 3个使用场景

  1. A factory constructor can check if it has a prepared reusable instance in an internal cache and return this instance or otherwise create a new one.
    避免创建过多的重复实例,如果已创建该实例,则从缓存中拿出来。

  2. You can for example have an abstract class A (which can't be instantiated) with a factory constructor that returns an instance of a concrete subclass of A depending for example on the arguments passed to the factory constructor.
    调用子类的构造函数(工厂模式 factory pattern)

  3. singleton pattern
    实现单例模式

四. 3个demo(初学dart,欢迎大家指正)

demo-1 创建缓存实例

(援引https://dart.dev/guides/language/language-tour#factory-constructors)

putIfAbsent的用法在文末

class Logger {
  final String name;
  // 缓存已创建的对象
  static final Map<String, Logger> _cache = <String, Logger>{}; 

  factory Logger(String name) {
  // 不理解putIfAbsent可以查看文末的简述
    return _cache.putIfAbsent(  
        name, () => Logger._internal(name));
  }

// 私有的构造函数
  Logger._internal(this.name){
    print("生成新实例:$name");
  }
}

// 测试
main() {
  var p1 = new Logger("1");
  var p2 = new Logger('22');
  var p3 = new Logger('1');// 相同对象直接访问缓存

  //identical会对两个对象的地址进行比较,相同返回true,
  //等同于 == ,好处是如果重写了==,那用identical 会更方便。
  print(identical(p1,p3)); 
}

> 生成新实例:1
> 生成新实例:2
> true

demo-2 调用子类的构造函数(工厂模式 factory pattern)

我还没感受到这种模式的优势..

abstract class Animal {
  String name;
  void getNoise();
  factory Animal(String type,String name) {
    switch(type) {
      case "cat":
        return new Cat(name);
      case "dog":
        return new Dog(name);
      default:
        throw "The '$type' is not an animal";
    }
  }
}

class Cat implements Animal {
  String name;
  Cat(this.name);
  @override
  void getNoise() {
    print("${this.name}: mew~");
  }
}

class Dog implements Animal {
  String name;
  Dog(this.name);
  @override
  void getNoise() {
    print("${this.name}: wang~");
  }
}

int main(){
  var cat = new Animal("cat","wiki");
  var dog = new Animal("dog","baobao");
  cat.getNoise();
  dog.getNoise();
  return  0;
}

> wiki: mew~
> baobao: wang~

demo-3 单例模式(singleton pattern)
class Singleton {
  static final Singleton _singleton = Singleton._internal();
  factory Singleton() {
    return _singleton;
  }
  Singleton._internal();
}
main() {
  var s1 = Singleton();
  var s2 = Singleton();
  print(identical(s1, s2));  
}

> true