案例介绍

一个有着基本功能的购物车程序长什么样子:

  1. //定义商品Item类
  2. class Item {
  3. double price;
  4. String name;
  5. Item(name, price) {
  6. this.name = name;
  7. this.price = price;
  8. }
  9. }
  10. //定义购物车类
  11. class ShoppingCart {
  12. String name;
  13. DateTime date;
  14. String code;
  15. List<Item> bookings;
  16. price() {
  17. double sum = 0.0;
  18. for(var i in bookings) {
  19. sum += i.price;
  20. }
  21. return sum;
  22. }
  23. ShoppingCart(name, code) {
  24. this.name = name;
  25. this.code = code;
  26. this.date = DateTime.now();
  27. }
  28. getInfo() {
  29. return '购物车信息:' +
  30. '\n-----------------------------' +
  31. '\n用户名: ' + name+
  32. '\n优惠码: ' + code +
  33. '\n总价: ' + price().toString() +
  34. '\n日期: ' + date.toString() +
  35. '\n-----------------------------';
  36. }
  37. }
  38. void main() {
  39. ShoppingCart sc = ShoppingCart('张三', '123456');
  40. sc.bookings = [Item('苹果',10.0), Item('鸭梨',20.0)];
  41. print(sc.getInfo());
  42. }

类抽象改造

  1. class Item {
  2. double price;
  3. String name;
  4. Item(this.name, this.price);
  5. }
  6. class ShoppingCart {
  7. String name;
  8. DateTime date;
  9. String code;
  10. List<Item> bookings;
  11. price() {...}
  12. //删掉了构造函数函数体
  13. ShoppingCart(this.name, this.code) : date = DateTime.now();
  14. ...
  15. }

抽象 name, price:

  1. class Meta {
  2. double price;
  3. String name;
  4. Meta(this.name, this.price);
  5. }
  6. class Item extends Meta{
  7. Item(name, price) : super(name, price);
  8. }
  9. class ShoppingCart extends Meta{
  10. DateTime date;
  11. String code;
  12. List<Item> bookings;
  13. double get price {...}
  14. ShoppingCart(name, this.code) : date = DateTime.now(),super(name,0);
  15. getInfo() {...}
  16. }

方法改造

我们先看看 price 属性的 get 方法:

  1. double get price {
  2. double sum = 0.0;
  3. for(var i in bookings) {
  4. sum += i.price;
  5. }
  6. return sum;
  7. }

使用 Dart 的箭头函数来进一步简化实现函数:

  1. class Item extends Meta{
  2. ...
  3. //重载了+运算符,合并商品为套餐商品
  4. Item operator+(Item item) => Item(name + item.name, price + item.price);
  5. }
  6. class ShoppingCart extends Meta{
  7. ...
  8. //把迭代求和改写为归纳合并
  9. double get price => bookings.reduce((value, element) => value + element).price;
  10. ...
  11. getInfo() {...}
  12. }

getInfo 方法如何优化:

  1. getInfo () => '''
  2. 购物车信息:
  3. -----------------------------
  4. 用户名: $name
  5. 优惠码: $code
  6. 总价: $price
  7. Date: $date
  8. -----------------------------
  9. ''';

对象初始化方式的优化

  1. class ShoppingCart extends Meta{
  2. ...
  3. //默认初始化方法,转发到withCode里
  4. ShoppingCart({name}) : this.withCode(name:name, code:null);
  5. //withCode初始化方法,使用语法糖和初始化列表进行赋值,并调用父类初始化方法
  6. ShoppingCart.withCode({name, this.code}) : date = DateTime.now(), super(name,0);
  7. //??运算符表示为code不为null,则用原值,否则使用默认值"没有"
  8. getInfo () => '''
  9. 购物车信息:
  10. -----------------------------
  11. 用户名: $name
  12. 优惠码: ${code??"没有"}
  13. 总价: $price
  14. Date: $date
  15. -----------------------------
  16. ''';
  17. }
  18. void main() {
  19. ShoppingCart sc = ShoppingCart.withCode(name:'张三', code:'123456');
  20. sc.bookings = [Item('苹果',10.0), Item('鸭梨',20.0)];
  21. print(sc.getInfo());
  22. ShoppingCart sc2 = ShoppingCart(name:'李四');
  23. sc2.bookings = [Item('香蕉',15.0), Item('西瓜',40.0)];
  24. print(sc2.getInfo());
  25. }

增加 PrintHelper 类,并调整 ShoppingCart 的声明:

  1. abstract class PrintHelper {
  2. printInfo() => print(getInfo());
  3. getInfo();
  4. }
  5. class ShoppingCart extends Meta with PrintHelper{
  6. ...
  7. }

总结

  1. class Meta {
  2. double price;
  3. String name;
  4. //成员变量初始化语法糖
  5. Meta(this.name, this.price);
  6. }
  7. class Item extends Meta{
  8. Item(name, price) : super(name, price);
  9. //重载+运算符,将商品对象合并为套餐商品
  10. Item operator+(Item item) => Item(name + item.name, price + item.price);
  11. }
  12. abstract class PrintHelper {
  13. printInfo() => print(getInfo());
  14. getInfo();
  15. }
  16. //with表示以非继承的方式复用了另一个类的成员变量及函数
  17. class ShoppingCart extends Meta with PrintHelper{
  18. DateTime date;
  19. String code;
  20. List<Item> bookings;
  21. //以归纳合并方式求和
  22. double get price => bookings.reduce((value, element) => value + element).price;
  23. //默认初始化函数,转发至withCode函数
  24. ShoppingCart({name}) : this.withCode(name:name, code:null);
  25. //withCode初始化方法,使用语法糖和初始化列表进行赋值,并调用父类初始化方法
  26. ShoppingCart.withCode({name, this.code}) : date = DateTime.now(), super(name,0);
  27. //??运算符表示为code不为null,则用原值,否则使用默认值"没有"
  28. @override
  29. getInfo() => '''
  30. 购物车信息:
  31. -----------------------------
  32. 用户名: $name
  33. 优惠码: ${code??"没有"}
  34. 总价: $price
  35. Date: $date
  36. -----------------------------
  37. ''';
  38. }
  39. void main() {
  40. ShoppingCart.withCode(name:'张三', code:'123456')
  41. ..bookings = [Item('苹果',10.0), Item('鸭梨',20.0)]
  42. ..printInfo();
  43. ShoppingCart(name:'李四')
  44. ..bookings = [Item('香蕉',15.0), Item('西瓜',40.0)]
  45. ..printInfo();
  46. }