Flutter 中的那些设计模式的写法(持续更新)

前言

我们都知道设计模式是相同的,同一种设计模式的理念不会因为语言不同而会有所改变,但是由于语法的差异,设计模式的写法也有所差异,本文会介绍一些flutter中常用设计模式的写法以及使用场景。

常见的设计模式有23种,按照类型可以细分为:
创建型模式

  • 单例模式 (Singleton)
  • 工厂方法模式 (Factory Method)
  • 抽象工厂模式 (Abstract Factory)
  • 建造者模式 (Builder)
  • 原型模式 (Prototype)

结构型模式

  • 适配器模式 (Adapter)
  • 桥接模式 (Bridge)
  • 组合模式 (Composite)
  • 装饰模式 (Decorator)
  • 外观模式 (Facade)
  • 享元模式 (Flyweight)
  • 代理模式 (Proxy)

行为型模式

  • 责任链模式 (Chain of Responsibility)
  • 命令模式 (Command)
  • 解释器模式 (Interpreter)
  • 迭代器模式 (Iterator)
  • 中介者模式 (Mediator)
  • 备忘录模式 (Memento)
  • 观察者模式 (Observer)
  • 状态模式 (State)
  • 策略模式 (Strategy)
  • 模板方法模式 (Template Method)
  • 访问者模式 (Visitor)

单例模式

想必对于大部分的开发来说,这是咱们接触最多的设计模式之一了。
单例模式(Singleton Pattern)理念

唯一实例: 单例模式保证了某个类只有一个实例存在。这意味着无论何时何地调用该类,只会返回同一个对象实例。
全局访问: 提供一个全局访问点来获取该唯一实例。通常通过一个静态方法或属性来实现。
延迟实例化: 单例模式通常支持延迟实例化,即在第一次请求时创建实例,以节省资源。

设计思路:

私有构造函数: 将类的构造函数设为私有,以防止外部通过普通构造方法创建实例。
静态实例: 使用静态变量存储类的唯一实例。
静态方法: 提供一个公共的静态方法或属性,返回该唯一实例。

代码实现

1. 饿汉式单例

这种方式在类加载时就创建实例,线程安全,但如果实例初始化开销大且不一定会用到,会造成资源浪费。

dart 复制代码
class Singleton {
  //私有构造函数
  Singleton._privateConstructor();

  // 静态实例
  static final Singleton instance = Singleton._privateConstructor();

  // 内部方法
  void printHello() {
    print('Hello');
  }
}
//调用方式
 Singleton.instance.printHello();

2. 懒汉式单例

这种方式在第一次使用时才创建实例,延迟加载。

dart 复制代码
class SingletonLazy {
  //私有构造
  SingletonLazy._privateConstructor();

  //静态实例
  static SingletonLazy? _instance;

  //获取实列方法
  static SingletonLazy getInstance() {
    if (_instance == null) {
      _instance = SingletonLazy._privateConstructor();
    }
    return _instance!;
  }
}

也可以通过dart中的工厂类来创建懒汉式

dart 复制代码
class SingletonFactory {
  // 私有构造函数
  SingletonFactory._privateConstructor();

  // 静态变量来存储唯一实例
  static SingletonFactory? _instance;

  // 工厂构造函数
  factory SingletonFactory() {
    if (_instance == null) {
      _instance = SingletonFactory._privateConstructor();
    }
    return _instance!;
  }

  void someMethod() {
    print('This is a method in SingletonFactory');
  }
}

3.静态内部类

这种方式利用 Dart 的静态内部类特性,既实现了延迟加载,又保证了线程安全。

dart 复制代码
class Singleton {
  // 私有构造函数
  Singleton._privateConstructor();

  // 静态内部类
  static final Singleton instance = _SingletonHolder.instance;

  // 内部类
  static class _SingletonHolder {
    static final Singleton instance = Singleton._privateConstructor();
  }
}

4. 懒汉式双重检查

额~~~写java过来的人条件反射就是,单例要考虑线程安全,加锁。。。

其实在flutter中,由于Flutter是单线程模式的,很少会有多线程切换的使用场景,它的异步操作是通过Future来实现的,其内部也是通过堆栈来实现阻塞(await)和插件队列执行,理论上是线程安全的,除非你非得使用Isolates ,但是Isolates一种多线程模型,每个 Isolate 拥有独立的内存空间,因此单例在不同的 Isolate 中不会共享。这意味着在 Dart 中,通常不需要担心传统意义上的多线程竞争条件。所以个人觉得,没有必要加锁考虑并发情况,非得写考虑 静态内部类

工厂设计模式

在 Flutter 中,工厂设计模式(Factory Pattern)是一种创建型设计模式,用于定义一个接口或抽象类以创建对象,但让子类决定要实例化的类。工厂模式可以将实例化对象的逻辑与使用对象的逻辑分离,提高代码的可扩展性和可维护性。

像支付(不同的支付类型)、日志、等都可以使用该模式

工厂模式的主要分类

  1. 简单工厂模式: 提供一个创建对象实例的方法,根据传入的参数决定创建哪种类型的对象。
  2. 抽象工厂模式:提供一个接口,用于创建相关或依赖对象的家族,而无需明确指定具体类。

简单工厂模式

简单工厂模式通过一个静态方法创建对象实例。

dart 复制代码
//对象实例子
abstract class Shape {
  void draw();
}
//实现抽象方法,重写自己的实例子
class Circle implements Shape {
  @override
  void draw() {
    print("Drawing a Circle");
  }
}

class Square implements Shape {
  @override
  void draw() {
    print("Drawing a Square");
  }
}

class ShapeFactory {
// 创建静态方法,通过传入不同的类型来判断要执行的工厂类
  static Shape createShape(String type) {
    if (type == 'circle') {
      return Circle();
    } else if (type == 'square') {
      return Square();
    } else {
      throw Exception("Shape type $type not recognized");
    }
  }
}
// 调用实现
void main() {
  Shape circle = ShapeFactory.createShape('circle');
  circle.draw(); // 输出: Drawing a Circle

  Shape square = ShapeFactory.createShape('square');
  square.draw(); // 输出: Drawing a Square
}

抽象工厂模式

抽象工厂模式用于创建相关或依赖对象的家族。

dart 复制代码
abstract class Button {
  void paint();
}

class WindowsButton implements Button {
  @override
  void paint() {
    print("Rendering a button in Windows style");
  }
}

class MacOSButton implements Button {
  @override
  void paint() {
    print("Rendering a button in MacOS style");
  }
}

abstract class GUIFactory {
  Button createButton();
}

class WindowsFactory implements GUIFactory {
  @override
  Button createButton() {
    return WindowsButton();
  }
}

class MacOSFactory implements GUIFactory {
  @override
  Button createButton() {
    return MacOSButton();
  }
}

void main() {
  GUIFactory factory = WindowsFactory();
  Button button = factory.createButton();
  button.paint(); // 输出: Rendering a button in Windows style

  factory = MacOSFactory();
  button = factory.createButton();
  button.paint(); // 输出: Rendering a button in MacOS style
}

策略设计模式

在 Flutter 中,策略模式(Strategy Pattern)是一种常用的设计模式,它允许你定义一系列算法,将每一个算法封装起来,并且使它们可以互相替换。而不用每次改动都去修改代码实现,策略模式可以让我们不用关注算法的具体实现是什么。

策略模式的结构

  • 策略接口(Strategy Interface): 定义算法或行为的接口。
  • 具体策略(Concrete Strategies): 实现策略接口的不同算法。
  • 上下文(Context): 维护对策略对象的引用,并在需要时调用策略对象的方法。

我们以用算不同类型的折扣为例。策略模式可以帮助我们在不同的折扣计算方法之间切换。

  1. 定义策略接口
    首先,定义一个策略接口,描述不同折扣算法的通用方法。
dart 复制代码
abstract class DiscountStrategy {
//计算折扣金额
  double calculateDiscount(double price);
}

2. 实现具体策略

为不同的折扣类型算法的具体的策略类。

dart 复制代码
//无折扣
class NoDiscountStrategy implements DiscountStrategy {
  @override
  double calculateDiscount(double price) {
    return 0.0;
  }
}
//具体折扣
class PercentageDiscountStrategy implements DiscountStrategy {
  final double percentage;

  PercentageDiscountStrategy(this.percentage);

  @override
  double calculateDiscount(double price) {
    return price * (percentage / 100);
  }
}
//全免
class FixedAmountDiscountStrategy implements DiscountStrategy {
  final double discountAmount;

  FixedAmountDiscountStrategy(this.discountAmount);

  @override
  double calculateDiscount(double price) {
    return discountAmount;
  }
}

3. 创建上下文

定义一个上下文类(Context),用于持有策略对象,并在需要时调用策略的方法。

dart 复制代码
class ShoppingCart {
  DiscountStrategy _discountStrategy;

  ShoppingCart(this._discountStrategy);

  void setDiscountStrategy(DiscountStrategy strategy) {
    _discountStrategy = strategy;
  }
  //计算打完折后的最终价格
  double calculateFinalPrice(double price) {
    double discount = _discountStrategy.calculateDiscount(price);
    return price - discount;
  }
}

4. 使用策略模式

现在可以在应用程序中使用策略模式,根据不同的需求动态选择折扣策略。

dart 复制代码
void main() {
  double itemPrice = 100.0;

  ShoppingCart cart = ShoppingCart(NoDiscountStrategy());
  print("Final price with no discount: ${cart.calculateFinalPrice(itemPrice)}");

  cart.setDiscountStrategy(PercentageDiscountStrategy(10));
  print("Final price with 10% discount: ${cart.calculateFinalPrice(itemPrice)}");

  cart.setDiscountStrategy(FixedAmountDiscountStrategy(15));
  print("Final price with $15 discount: ${cart.calculateFinalPrice(itemPrice)}");
}

建造者模式(Builder Pattern)

建造者模式(Builder Pattern)是一种创建型设计模式,它允许使用者一步步构建一个复杂对象。与直接使用构造函数或工厂模式不同,建造者模式提供了一种灵活的方式来创建对象,特别是当对象的创建过程涉及多个步骤或需要复杂配置时。

在 Flutter 中,建造者模式(链式调用)可以用于构建复杂的 UI 组件或对象配置,像UI组件的封装使用构建者模式是非常常用的。

建造者模式的结构

  • 产品(Product): 需要构建的复杂对象。
  • 建造者接口(Builder Interface): 定义创建产品对象的所有步骤。
  • 具体建造者(Concrete Builder): 实现 Builder 接口,并提供创建产品的具体步骤。
  • 指挥者(Director): 控制构建过程,按顺序调用建造者中的各个步骤。

下面以封装一个UI组件为例:
1. 定义产品

首先,定义需要创建的复杂对象(对象参数比较多,或者链路很长)。

dart 复制代码
class ComplexWidget {
  String? title;
  String? imageUrl;
  String? description;

  @override
  String toString() {
    return 'ComplexWidget(title: $title, imageUrl: $imageUrl, description: $description)';
  }
}

2. 定义建造者接口

定义一个接口,描述创建产品的步骤。

dart 复制代码
abstract class ComplexWidgetBuilder {
  void setTitle(String title);
  void setImageUrl(String imageUrl);
  void setDescription(String description);
  ComplexWidget getResult();
}

3. 实现具体建造者

实现建造者接口,提供具体的构建步骤。

dart 复制代码
class ConcreteComplexWidgetBuilder implements ComplexWidgetBuilder {
  final ComplexWidget _complexWidget = ComplexWidget();

  @override
  void setTitle(String title) {
    _complexWidget.title = title;
  }

  @override
  void setImageUrl(String imageUrl) {
    _complexWidget.imageUrl = imageUrl;
  }

  @override
  void setDescription(String description) {
    _complexWidget.description = description;
  }

  @override
  ComplexWidget getResult() {
    return _complexWidget;
  }
}

4. 定义指挥者

定义一个指挥者类,用于控制构建过程。

dart 复制代码
class Director {
  late ComplexWidgetBuilder _builder;

  void setBuilder(ComplexWidgetBuilder builder) {
    _builder = builder;
  }

  ComplexWidget buildCompleteWidget() {
    _builder.setTitle("Sample Title");
    _builder.setImageUrl("http://example.com/image.png");
    _builder.setDescription("This is a sample description.");
    return _builder.getResult();
  }
}

5. 使用建造者模式

在应用程序中使用建造者模式来创建复杂对象。

dart 复制代码
void main() {
  Director director = Director();
  ComplexWidgetBuilder builder = ConcreteComplexWidgetBuilder();

  director.setBuilder(builder);
  ComplexWidget widget = director.buildCompleteWidget();

  print(widget);
  // 输出: ComplexWidget(title: Sample Title, imageUrl: http://example.com/image.png, description: This is a sample description.)
}

未完待续

后面慢慢会把常用的设计模式都在这里做更新。。。

每个设计模式都有自己的优缺点,其实适合自己的才是最合理的,不要为了设计代码而设计代码,如果不理解业务场景强上设计模式,只会让代码写的更复杂

相关推荐
千里马学框架1 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台1 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone1 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc1 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo1 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077001 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼1 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone1 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen1 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone1 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui