UMVCSL3——Model和Proxy

本章代码关键字

1
2
3
4
5
Proxy                                            //Proxy基类,任何在PureMVC内作为Proxy代理的类都应该继承该类,可以实现对其关联数据的操作
proxy.Name //字符串常量,其派生类里可以覆盖该Name,使用自己的字符串作为名字
proxy.proxyName //获取该proxy派生类的Name
proxy.Data //该proxy派生类对象关联的Model类对象
Proxy(string proxyName, object data = null) //Proxy的构造函数,继承该类必须要声明构造函数调用该构造函数,用于初始化名字和关联的对象

Model

这里的 Model​ 就是数据结构类,单纯存储内容的类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/// <summary>
/// 玩家数据结构
/// </summary>
public class PlayerDataObject
{
//申明一堆玩家属性相关的变量
public string playerName;
public int lev;
public int money;
public int gem;
public int power;

public int hp;
public int atk;
public int def;
public int crit;
public int miss;
public int luck;
}

Proxy

数据代理类,在这里我们使用数据代理类来为数据结构类进行代理,数据更新相关逻辑在这里处理,所有的数据代理类都要继承Proxy

Proxy的重点

Proxy​ 的重点在于其构造函数,先来看看 Proxy基类的构造函数具体代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//Proxy类的部分代码
public class Proxy: Notifier, IProxy
{
//Proxy的类名的常量,在需要填入"Proxy"的情况下我们可以直接使用该常量,接下来我们要在其派生类里隐藏掉定义其自己的NAME
public const string NAME = "Proxy";

//Proxy的构造函数,由于该构造函数的存在,其派生类都需要在构造函数传入该类构造函数的proxyName参数
//这个proxyName非常重要!!!之后的Facade要通过这个名字来获取其派生代理类对象!!!
//data则是该代理对象关联的数据结构对象
public Proxy(string proxyName, object data = null)
{
ProxyName = proxyName ?? NAME;
if (data != null) Data = data;
}

public string ProxyName { get; protected set; }

public object Data { get; set; }
}

由于基类的这个构造函数的存在,且没有无参构造函数,我们的数据代理类继承该类时,
必须要声明构造函数调用基类构造函数为proxyName赋值,并关联要代理的数据结构对象Data
因此数据代理类的构造函数将是数据结构类的重点(必须调用父类构造函数的具体原理详见:CS3L15——继承中的构造函数)

对于proxyName​这个参数,我们需要在声明构造函数时,就调用基类的构造函数传入proxyName
(因为 Facade​ 要通过这个名字来获取这个代理,它非常重要,必须在对象实例化时就将其赋值)
在这里我们将 PlayerProxy​ 的类名作为代理名,为了防止字符串拼错带来的问题,
我们可以显式的隐藏基类的NAME​常量,声明新的 NAME​ 常量并为其初始化为PlayerProxy​,代码如下:

1
2
3
4
5
6
7
public class PlayerProxy : Proxy
{
//这里显式的将父类的NAME隐藏了,因此再调用PlayerProxy.NAME得到的将是这里的名字
public new const string NAME = "PlayerProxy";
//声明构造函数时调用基类构造函数,传入该类类名
public PlayerProxy() : base(PlayerProxy.NAME) { }
}

接下来是 data​ 参数,这个 data​ 将是数据代理类要代理的对象,也就是要操作数据的数据结构类对象
对于 data​ 这个参数,我们有两种赋值方法

  1. 通过构造函数的参数传入要代理的对象,在关联前可以进行初始化等操作,这种适合需要外部传入代理对象的场景的代理类(例如代理多个类)

    1
    2
    3
    4
    public PlayerProxy(PlayerDataObject data) : base(PlayerProxy.NAME, data)
    {
    //在这里可以初始化外部传入的数据
    }
  2. 无需外部传入,直接构造函数内直接初始化一个要构造的对象,并将其关联到自己的data​上(适合仅代理一个类的代理类)

    1
    2
    3
    4
    5
    6
    7
    8
    public PlayerProxy() : base(PlayerProxy.NAME)
    {
    //我们可以直接在构造函数中,初始化一个数据,进行管理
    PlayerDataObject data = new PlayerDataObject();
    //在这里初始化对象
    //赋值给自己的Data进行关联
    Data = data;
    }

最终得到的构造函数代码如下:

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
//写构造函数
//重要点
//1.代理的名字!!!!(非常重要,之后的Facade要通过这个名字来获取这个代理)
//2.代理相关的数据!!!!(有两种关联方法,
// 第一种是在该类的构造函数里添加要关联的类的参数,再将该参数传入base的构造函数内,这种方法适用于外部传入对象进行关联
// 写法是:public PlayerProxy(PlayerDataObject data) : base(PlayerProxy.NAME, data) { }
// 第二种,不需要参数,直接构造函数内初始化要关联的对象,并将该对象关联给基类的Data)

public PlayerProxy() : base(PlayerProxy.NAME)
{
//我们可以直接在构造函数中,初始化一个数据,进行管理
PlayerDataObject data = new PlayerDataObject();

//初始化对象
data.playerName = PlayerPrefs.GetString("PlayerName", "MrLIU");
data.lev = PlayerPrefs.GetInt("PlayerLev", 1);
data.money = PlayerPrefs.GetInt("PlayerMoney", 9999);
data.gem = PlayerPrefs.GetInt("PlayerGem", 8888);
data.power = PlayerPrefs.GetInt("PlayerPower", 99);

data.hp = PlayerPrefs.GetInt("PlayerHp", 100);
data.atk = PlayerPrefs.GetInt("PlayerAtk", 20);
data.def = PlayerPrefs.GetInt("PlayerDef", 10);
data.crit = PlayerPrefs.GetInt("PlayerCrit", 20);
data.miss = PlayerPrefs.GetInt("PlayerMiss", 10);
data.luck = PlayerPrefs.GetInt("PlayerLuck", 40);

//赋值给自己的Data进行关联
Data = data;
}

之后,我们在代理类里实现数据操作方法以及数据更新相关逻辑

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
using PureMVC.Patterns.Proxy;
using UnityEngine;

/// <summary>
/// 玩家数据代理对象,主要处理玩家数据更新相关逻辑
/// </summary>
public class PlayerProxy : Proxy
{
//这里显式的将父类的NAME隐藏了,因此再调用PlayerProxy.NAME得到的将是这里的名字
public new const string NAME = "PlayerProxy";
//继承Proxy父类
//写我们的构造函数

//写构造函数
//重要点
//1.代理的名字!!!!(非常重要,之后的Facade要通过这个名字来获取这个代理)
//2.代理相关的数据!!!!(有两种关联方法,
// 第一种是在该类的构造函数里添加要关联的类的参数,再将该参数传入base的构造函数内,这种方法适用于外部传入对象进行关联
// 写法是:public PlayerProxy(PlayerDataObject data) : base(PlayerProxy.NAME, data) { }
// 第二种,不需要参数,直接构造函数内初始化要关联的对象,并将该对象关联给基类的Data)

public PlayerProxy() : base(PlayerProxy.NAME)
{
//我们可以直接在构造函数中,初始化一个数据,进行管理
PlayerDataObject data = new PlayerDataObject();

//初始化对象
data.playerName = PlayerPrefs.GetString("PlayerName", "MrLIU");
data.lev = PlayerPrefs.GetInt("PlayerLev", 1);
data.money = PlayerPrefs.GetInt("PlayerMoney", 9999);
data.gem = PlayerPrefs.GetInt("PlayerGem", 8888);
data.power = PlayerPrefs.GetInt("PlayerPower", 99);

data.hp = PlayerPrefs.GetInt("PlayerHp", 100);
data.atk = PlayerPrefs.GetInt("PlayerAtk", 20);
data.def = PlayerPrefs.GetInt("PlayerDef", 10);
data.crit = PlayerPrefs.GetInt("PlayerCrit", 20);
data.miss = PlayerPrefs.GetInt("PlayerMiss", 10);
data.luck = PlayerPrefs.GetInt("PlayerLuck", 40);

//赋值给自己的Data进行关联
Data = data;
}

public void LevelUp()
{
//先转换为data
PlayerDataObject data = Data as PlayerDataObject;
//升级 改变内容
data.lev += 1;
data.hp += data.lev;
data.atk += data.lev;
data.def += data.lev;
data.crit += data.lev;
data.miss += data.lev;
data.luck += data.lev;
//将数据内容存储到本地
SaveData();
}

private void SaveData()
{
PlayerDataObject data = Data as PlayerDataObject;

PlayerPrefs.SetString("PlayerName", data.playerName);
PlayerPrefs.SetInt("PlayerLev", data.lev);
PlayerPrefs.SetInt("PlayerMoney", data.money);
PlayerPrefs.SetInt("PlayerGem", data.gem);
PlayerPrefs.SetInt("PlayerPower", data.power);

PlayerPrefs.SetInt("PlayerHp", data.hp);
PlayerPrefs.SetInt("PlayerAtk", data.atk);
PlayerPrefs.SetInt("PlayerDef", data.def);
PlayerPrefs.SetInt("PlayerCrit", data.crit);
PlayerPrefs.SetInt("PlayerMiss", data.miss);
PlayerPrefs.SetInt("PlayerLuck", data.luck);
}
}