首页 Flutter 设计模式原型模式
文章
取消

Flutter 设计模式原型模式

原型模式定义

原型模式(Prototype Pattern)它属于创建型模式。原型模式主要作用于用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。在这里,原型实例指定了要创建的对象的种类。用这种方式创建对象非常高效,根本无须知道对象创建的细节。

原型模式由来

数据库需要付出高代价的初始化过程才能被创建(类的实例化),那么每次都去重复性的创建无疑对系统性能有影响,那么这个时候可以缓存该对象,在下一个需要使用到它的时候就返回它的克隆,以减少对数据库的调用。

原型模式结构

  • AbstractPrototype:抽象原型角色

    规定了具体原型对象必须实现的接口

  • ConcretePrototype:具体原型角色

    实现抽象原型类的 clone() 方法,它是可被复制的对象。

案例分析

骑上我心爱的小摩托~~~,哈,扯远了。一辆雅迪(yadea)电动车,有名称、颜色、制动系统、轮毂、轮胎、座椅等元件构建组件而成,我们先用一种最简单的方式来实现。

方案一:初始设计

1、定义雅迪类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Yadea {

  // 名称
  final String name;
  // 颜色
  String color;
  // 制动
  final String brake;
  // 座椅
  final String seat;
  // 更多属性....

  Yadea(this.name, this.color, this.brake, this.seat);
}

2、使用

1
2
3
4
5
6
7
8
9
10
11
void main(List<String> args) {

  // 红色的雅迪
  Yadea yadeaRed = Yadea("小毛驴", "红色", "手动", "沙发");
  print("雅迪的名字 ${yadeaRed.name}, 颜色是 ${yadeaRed.color}, 制动系统是 ${yadeaRed.brake}, 座椅是 ${yadeaRed.seat}");

  // 粉色的雅迪
  Yadea yadeaPink = Yadea("小毛驴", "粉色", "手动", "沙发");
  print("雅迪的名字 ${yadeaPink.name}, 颜色是 ${yadeaPink.color}, 制动系统是 ${yadeaPink.brake}, 座椅是 ${yadeaPink.seat}");
  
}

3、运行结果

1
2
3
4
Connecting to VM Service at http://127.0.0.1:63303/bm2yRuPLcNA=/
雅迪的名字 小毛驴, 颜色是 红色, 制动系统是 手动, 座椅是 沙发
雅迪的名字 小毛驴, 颜色是 粉色, 制动系统是 手动, 座椅是 沙发
Exited

4、完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
void main(List<String> args) {

  // 红色的雅迪
  Yadea yadeaRed = Yadea("小毛驴", "红色", "手动", "沙发");
  print("雅迪的名字 ${yadeaRed.name}, 颜色是 ${yadeaRed.color}, 制动系统是 ${yadeaRed.brake}, 座椅是 ${yadeaRed.seat}");

  // 粉色的雅迪
  Yadea yadeaPink = Yadea("小毛驴", "粉色", "手动", "沙发");
  print("雅迪的名字 ${yadeaPink.name}, 颜色是 ${yadeaPink.color}, 制动系统是 ${yadeaPink.brake}, 座椅是 ${yadeaPink.seat}");
  
}

class Yadea {

  // 名称
  final String name;
  // 颜色
  final String color;
  // 制动
  final String brake;
  // 座椅
  final String seat;
  // 更多属性....

  Yadea(this.name, this.color, this.brake, this.seat);
}

5、分析

我们从上面的案例中发现,雅迪的其他属性都一样,就只是颜色不一样,对象的创建过程确把每个属性都重新赋值一遍,如果属性有二三十个的时候,那对象的创建过程就显得尤为复杂,我们来看下如何优化。

方案二:原型模式

1、创建原型角色

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Yadea {

  // 名称
  final String name;
  // 颜色
  String color;
  // 制动
  final String brake;
  // 座椅
  final String seat;
  // 更多属性....

  Yadea(this.name, this.color, this.brake, this.seat);
}

2、具体原型角色

1
2
3
class YadeaClone extends Yadea {
  YadeaClone(Yadea yadea) : super(yadea.name, yadea.color, yadea.brake, yadea.seat);
}

3、使用

1
2
3
4
5
6
7
8
9
10
11
void main(List<String> args) {
  // 原型
  Yadea yadea = Yadea("小毛驴", "红色", "手动", "沙发");
  print("雅迪的名字 ${yadea.name}, 颜色是 ${yadea.color}, 制动系统是 ${yadea.brake}, 座椅是 ${yadea.seat}");

  // 快速克隆
  YadeaClone yadeaClone = YadeaClone(yadea);
  yadeaClone.color = "粉色";
  print("雅迪的名字 ${yadeaClone.name}, 颜色是 ${yadeaClone.color}, 制动系统是 ${yadeaClone.brake}, 座椅是 ${yadeaClone.seat}");

}

4、运行结果

1
2
3
4
Connecting to VM Service at http://127.0.0.1:63303/bm2yRuPLcNA=/
雅迪的名字 小毛驴, 颜色是 红色, 制动系统是 手动, 座椅是 沙发
雅迪的名字 小毛驴, 颜色是 粉色, 制动系统是 手动, 座椅是 沙发
Exited

5、完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
void main(List<String> args) {
  // 原型
  Yadea yadea = Yadea("小毛驴", "红色", "手动", "沙发");
  print("雅迪的名字 ${yadea.name}, 颜色是 ${yadea.color}, 制动系统是 ${yadea.brake}, 座椅是 ${yadea.seat}");

  // 快速克隆
  YadeaClone yadeaClone = YadeaClone(yadea);
  yadeaClone.color = "粉色";
  print("雅迪的名字 ${yadeaClone.name}, 颜色是 ${yadeaClone.color}, 制动系统是 ${yadeaClone.brake}, 座椅是 ${yadeaClone.seat}");

}

class Yadea {

  // 名称
  final String name;
  // 颜色
  String color;
  // 制动
  final String brake;
  // 座椅
  final String seat;
  // 更多属性....

  Yadea(this.name, this.color, this.brake, this.seat);
}

class YadeaClone extends Yadea {
  YadeaClone(Yadea yadea) : super(yadea.name, yadea.color, yadea.brake, yadea.seat);
}

6、分析

我们使用具体原型角色的方式,利用父类的构造方法进行快速克隆对象。这样是的创建过程极其简单。

总结

原型模式优点

  • 快速复制对象
  • 简化创建对象的过程

原型模式缺点

  • 需要单独为一个类配置克隆方法
  • 克隆方法位于类内部,如果类结构被改造,那么就需要修改代码,违背开闭原则

本文由作者按照 CC BY 4.0 进行授权

Flutter 设计模式单例模式

Flutter 设计模式建造者模式