Flutter从头到尾设计一款简单的五子棋游戏(四) | 设计模式代码完结

630 阅读3分钟

image.png 开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第13天,点击查看活动详情

前言

在前面几篇的文章中,我们已经今天在复习了原有的享元模式上,再介绍了桥接模式以及状态模式。完成了关于棋子的创建以及玩家的状态我们也就已经设计完成,现在我们将把悔棋、以及App主题变换加上,所有设计模式基本就大功告成了。注意,我们这次的设计是完全使用Flutter自带的包进行设计。

正文

1. 设计总图纸

现在我们先放个整个项目所使用到的类图的概览图。而后,我们将把主题设计使用的抽象工厂模式以及悔棋所使用的备忘录模式给大家讲解。

image.png

2. 主题切换——抽象工厂模式

考虑到玩家可能会在晚上偷偷在被窝玩手机,我们专门设计了一套深色的主题,更好地对玩家的眼睛进行保护。那这两套主题怎么设计与切换呢?

由于主题所需要进行变换的一些组件都是固定的,因此在这里我们使用抽象工厂模式。

类图如下:

image.png

对于抽象工厂,我们定义如下:

abstract class ThemeFactory {  
  Theme getTheme();  
}

对于蓝色的默认主题工厂(具体工厂),我们定义如下:

class BlueThemeFactory extends ThemeFactory{  
  @override  
  Theme getTheme() {  
    return new BlueTheme();  
  }  
}

同样地,对于深色的主题工厂(具体工厂),我们定义如下:

class BlackThemeFactory extends ThemeFactory{  
  @override  
  Theme getTheme() {  
    return new BlackTheme();  
  }  
}

工厂类的设计就完成了,下面我们对着类图设计产品类,下方是抽象产品:

abstract class Theme{  
  Color getThemeColor();  
}

而后我们进行具体的产品设计,下方分别是蓝色主题类,以及深色主题类:


import 'Theme.dart' as t;// 注意,这里的theme是刚刚我们自己定义的,因为跟Flutter自己的重名,所有需要使用别名

class BlueTheme extends t.Theme{  
  @override  
  Color getThemeColor() {  
    return Colors.blue;  
  }  
}
  
class BlackTheme extends t.Theme{  
  @override  
  Color getThemeColor() {  
    return Colors.black;  
  }  
}

注意,这里的theme是刚刚我们自己定义的,因为跟Flutter自己的重名,所以需要使用别名。

到这里,主题的设计模式就设计完了。

效果如下:

image.png

image.png

3.玩家的下棋步骤记录——备忘录模式

首先,先放上类图:

image.png

对于Checkerboard(原发器)的设计如下:

class Checkerboard {  
  
  Checkerboard._();  
  
  static Checkerboard? _originator;  
  
  static getInstance(){  
    if( _originator == null){  
      _originator = Checkerboard._();  
    }  
    return _originator;  
  }  
  
  bool _canAdd = true; //是否需要添加  
  
  List<Position> _state = [];  
  
  List<Position> get state{  
    return _state;  
  }  
  
  CareTaker _careTaker = CareTaker();  
  
  add(Position position) {  
    if(_canAdd) { //因为每次渲染完默认会把最后一个下棋的位置添加上,但在悔棋阶段最后一个是不需要,因此需要这个判断。  
      _state.add(position);  
      _careTaker.add(_save());  
    }  
    _canAdd = true;  
  }  
  
  _from(Memo memo) {  
    this._state = memo.state;  
  }  
  
  Memo _save() {  
    return new Memo()..state.addAll(this._state);  
  }  
  
  clean(){  
    _state = [];  
  }  
  
  undo() {  
    Memo memo = _careTaker.getLast();  
    _from(memo);  
    _canAdd = false;  
  }  
}

Checkerboard这里就主要负责对外暴露使用了,其内部有一个负责人类。

而下面的负责人类则主要将信息进行缓存以及记录,是真正的缓存保存者。

class CareTaker{  
  List<Memo> mementoList = [];  
  
  void add(Memo memo) {  
    mementoList.add(memo);  
    if (mementoList.length > 10) {  
      mementoList.removeRange(0, 1);  
    }  
  }  
  
  Memo get(int index){  
    return mementoList[index];  
  }  
  
  Memo getLast() {  
    Memo memo = mementoList[mementoList.length-3];  
    mementoList.removeLast();  
    mementoList.removeLast();  
    return memo;  
  }  
}

下面的Memo则是一个数据类,保存了棋盘上所有棋子的位置数据。

class Memo {  
  List<Position> state = [];  
}

4.总结

至此,所有的设计模式都已经设计完成了,我们下一步的目标就是将这些设计模式与Flutter融合起来,让整个App能动起来,用起来。