为了账号安全,请及时绑定邮箱和手机立即绑定

Dart命名工厂构造方法资料详解

标签:
设计模式
概述

本文详细介绍了Dart命名工厂构造方法的使用和实现,包括工厂构造方法的基本概念、语法及其应用场景。文章还深入探讨了命名构造方法的作用和定义方式,并提供了多个实例来说明如何结合工厂构造方法和命名构造方法进行对象的初始化和管理。文中详细阐述了dart命名工厂构造方法资料,帮助读者全面理解这两种构造方法的使用场景和优势。

Dart工厂构造方法简介

什么是工厂构造方法

工厂构造方法是一种特殊类型的构造函数,它允许在Dart中创建和初始化对象的灵活性。与普通构造方法不同,工厂构造方法并不直接创建实例,而是通过返回一个现有实例或新建实例来完成初始化。工厂构造方法适用于当直接创建实例需要额外逻辑处理,或者需要缓存实例等场景。

工厂构造方法的基本语法

在Dart中,工厂构造方法使用关键字factory来声明。工厂构造方法的基本语法如下:

factory ClassName.factoryName([type parameters]) {
  // 逻辑处理
  return instance;
}

其中,ClassName是包含工厂构造方法的类名,factoryName是工厂构造方法的名字。工厂构造方法可以有参数,也可以没有参数。

命名构造方法的基本概念

什么是命名构造方法

命名构造方法允许在类中定义一个具有特定功能的构造方法,它在创建对象时提供更多的灵活性。命名构造方法的名字可以自定义,可以与类名相同也可以不同。命名构造方法的名字通常用来表示其特定的行为或初始化方式。

命名构造方法的作用

命名构造方法的主要作用包括:

  • 提供多种初始化方式。
  • 用于创建具有特定属性或状态的对象。
  • 在创建对象时提供额外的逻辑处理。

工厂构造方法与命名构造方法的区别

工厂构造方法和命名构造方法虽然都可以用于对象初始化,但它们之间存在一些关键的区别:

  • 工厂构造方法:工厂构造方法通过factory关键字声明,主要用于控制对象实例的创建和初始化。工厂构造方法可以返回一个已存在的对象实例或创建新的对象实例。
  • 命名构造方法:命名构造方法通过在构造方法名前加上特定名称来声明,主要用于提供多种初始化方式。命名构造方法可以直接创建对象实例。

如何在Dart中定义工厂构造方法

创建普通类的工厂构造方法

创建普通类的工厂构造方法时,可以在类中定义一个以factory关键字开头的方法。下面是一个简单的例子,展示了如何创建一个普通类的工厂构造方法:

class Singleton {
  Singleton._internal() {
    print("Singleton._internal");
  }

  factory Singleton() {
    print("Singleton factory");
    return Singleton._internal();
  }
}

void main() {
  var instance1 = Singleton();
  var instance2 = Singleton();
  print(instance1 == instance2); // 输出:true
}

在这个例子中,Singleton类使用了工厂构造方法来控制实例的创建。每当调用Singleton()时,都会打印出"Singleton factory",并返回一个Singleton._internal()的实例。这里Singleton._internal()是一个私有构造函数,只在工厂构造方法中使用。

创建抽象类的工厂构造方法

工厂构造方法也可以应用于抽象类。抽象类本身不能被实例化,但可以包含工厂构造方法,这些工厂构造方法可以返回其子类的实例。

abstract class AbstractFactory {
  factory AbstractFactory() {
    return getConcreteInstance();
  }

  static AbstractFactory getConcreteInstance() {
    return ConcreteFactory();
  }
}

class ConcreteFactory extends AbstractFactory {}

void main() {
  var instance = AbstractFactory();
  print(instance is ConcreteFactory); // 输出:true
}

在这个例子中,AbstractFactory是一个抽象类,它包含一个工厂构造方法AbstractFactory()。工厂构造方法通过调用静态方法getConcreteInstance()来返回一个ConcreteFactory实例。

如何在Dart中定义命名构造方法

定义简单的命名构造方法

命名构造方法允许为一个类定义多个初始化方式。下面是一个简单的例子,展示了如何定义一个简单的命名构造方法:

class Person {
  String name;
  int age;

  Person(String name, int age) {
    this.name = name;
    this.age = age;
  }

  Person.fromJson(Map<String, dynamic> json)
      : name = json['name'],
        age = json['age'];
}

void main() {
  var person1 = Person('张三', 25);
  var person2 = Person.fromJson({"name": "李四", "age": 30});
  print(person1.name); // 输出:张三
  print(person2.age); // 输出:30
}

在这个例子中,Person类定义了一个普通构造方法Person(String name, int age)和一个命名构造方法Person.fromJson(Map<String, dynamic> json)。命名构造方法通过从JSON字典中解析数据来初始化对象。

定义带参数的命名构造方法

命名构造方法还可以带有参数。下面的例子展示了如何定义一个带参数的命名构造方法:

class Rectangle {
  double width;
  double height;

  Rectangle(double width, double height) {
    this.width = width;
    this.height = height;
  }

  factory Rectangle.withLength(double length) {
    return Rectangle(length, length);
  }

  factory Rectangle.withWidthAndHeight(double width, double height) {
    if (width < 0 || height < 0) {
      throw ArgumentError("Width and height must be greater than 0");
    }
    return Rectangle(width, height);
  }
}

void main() {
  var rect1 = Rectangle.withLength(5);
  var rect2 = Rectangle.withWidthAndHeight(10, 20);
  print(rect1.width); // 输出:5
  print(rect2.height); // 输出:20
}

在这个例子中,Rectangle类定义了两个带参数的命名构造方法:

  • Rectangle.withLength(double length):这个命名构造方法接受一个参数length,并返回一个正方形的实例。
  • Rectangle.withWidthAndHeight(double width, double height):这个命名构造方法接受两个参数widthheight,并且在参数小于0时抛出异常。

工厂构造方法与命名构造方法的结合使用

结合使用工厂构造方法和命名构造方法可以提供更大的灵活性和控制力。例如,工厂构造方法可以用来控制对象的生命周期,而命名构造方法可以用来提供多种初始化方式。下面是一个结合使用工厂构造方法和命名构造方法的例子:

class Config {
  String name;
  int value;

  Config._internal(String name, int value) {
    this.name = name;
    this.value = value;
  }

  factory Config.fromJson(Map<String, dynamic> json) {
    return Config._internal(json['name'], json['value']);
  }

  factory Config.withNameAndValue(String name, int value) {
    return Config._internal(name, value);
  }

  static Config _instance;

  factory Config.getInstance() {
    if (_instance == null) {
      _instance = Config.withNameAndValue("defaultName", 100);
    }
    return _instance;
  }
}

void main() {
  var config1 = Config.fromJson({"name": "jsonName", "value": 1000});
  var config2 = Config.withNameAndValue("nameFromParam", 200);
  var config3 = Config.getInstance();
  print(config1.name); // 输出:jsonName
  print(config2.value); // 输出:200
  print(config3.name); // 输出:defaultName
}

在这个例子中,Config类包含了一个工厂构造方法Config.fromJson(Map<String, dynamic> json)和一个命名构造方法Config.withNameAndValue(String name, int value)。此外,还有一个工厂构造方法Config.getInstance()用于创建单例实例。通过这些构造方法,可以在不同的场景下灵活地初始化Config类的实例。

实际案例与练习

实战案例:使用工厂和命名构造方法实现数据解析

假设我们有一个API返回JSON格式的数据,我们希望根据不同的数据格式解析出不同的对象。下面是一个使用工厂构造方法和命名构造方法实现数据解析的例子:

class User {
  String name;
  int age;

  User._internal(String name, int age) {
    this.name = name;
    this.age = age;
  }

  factory User.fromJson(Map<String, dynamic> json) {
    return User._internal(json['name'], json['age']);
  }

  factory User.fromApi(Map<String, dynamic> data) {
    if (data['type'] == 'admin') {
      return Admin.fromJson(data['adminData']);
    } else {
      return User.fromJson(data['userData']);
    }
  }
}

class Admin {
  String adminName;
  String adminRole;

  Admin._internal(String name, String role) {
    this.adminName = name;
    this.adminRole = role;
  }

  factory Admin.fromJson(Map<String, dynamic> json) {
    return Admin._internal(json['name'], json['role']);
  }
}

void main() {
  Map<String, dynamic> adminData = {
    'type': 'admin',
    'adminData': {'name': 'adminUser', 'role': 'adminRole'}
  };

  Map<String, dynamic> userData = {'name': 'normalUser', 'age': 25};

  var adminUser = User.fromApi(adminData);
  var normalUser = User.fromApi(userData);

  print(adminUser.name); // 输出:adminUser
  print(normalUser.age); // 输出:25
}

在这个例子中,User类使用了工厂构造方法User.fromApi(Map<String, dynamic> data)来根据不同的数据格式解析出不同的对象。如果数据类型为admin,则创建Admin对象;否则,创建User对象。Admin类同样使用工厂构造方法Admin.fromJson(Map<String, dynamic> json)来解析admin数据。

小练习:自定义类并添加工厂和命名构造方法

请自定义一个类Book,并为其添加工厂构造方法和命名构造方法。工厂构造方法可以用于创建单例实例,命名构造方法可以用来初始化不同类型的书。

class Book {
  String title;
  String author;
  int pages;

  Book._internal(String title, String author, int pages) {
    this.title = title;
    this.author = author;
    this.pages = pages;
  }

  factory Book.fromJson(Map<String, dynamic> json) {
    return Book._internal(json['title'], json['author'], json['pages']);
  }

  factory Book.withMandatoryProperties(String title, String author) {
    return Book._internal(title, author, 0);
  }

  static Book _instance;

  factory Book.getInstance() {
    if (_instance == null) {
      _instance = Book.withMandatoryProperties("defaultTitle", "defaultAuthor");
    }
    return _instance;
  }
}

void main() {
  var book1 = Book.fromJson({"title": "titleFromJson", "author": "authorFromJson", "pages": 300});
  var book2 = Book.withMandatoryProperties("titleFromParam", "authorFromParam");
  var book3 = Book.getInstance();
  print(book1.title); // 输出:titleFromJson
  print(book2.author); // 输出:authorFromParam
  print(book3.title); // 输出:defaultTitle
}

在这个练习中,你自定义了一个Book类,并为其添加了工厂构造方法Book.getInstance()和命名构造方法Book.withMandatoryProperties(String title, String author)。工厂构造方法用于创建单例实例,命名构造方法用于初始化具有特定属性的书。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消