对数据操作封装的一点心得

来源:互联网 发布:是 大臣 知乎 编辑:程序博客网 时间:2024/05/22 05:18

假设缓存中数据的格式如下所示:

 

id | name level exp time

 

下面,我们考虑对数据操作进行封装,先定义一个类

 

class CCacheData;

 

在对数据进行操作时,可能需要读写name,于是我们写了一个接口,这个接口会实时更新缓存

 

class CCacheData

{

    SetName(string &name);

};

 

由于业务需要,我们需要一个接口更新exp,于是又多了一个接口 

 

class CCacheData

{

    SetName(string &name);

    SetExp(int exp);

};

 

由于业务需要,我们需要一个接口更新exp的同时,更新time,于是又多了一个接口

 

class CCacheData

{

    SetName(string &name);

    SetExp(int exp);

    SetExp(int exp, int time);

}; 

 

由于业务需要,我们需要一个接口更新level,于是又多了一个接口

 

class CCacheData

{

    SetName(string &name);

    SetExp(int exp);

    SetExp(int exp, int time);

    SetLevel(int level);

}; 

 

由于业务需要,我们需要一个接口更新level的同时,更新time,于是又多了一个接口

 

class CCacheData

{

    SetName(string &name);

    SetExp(int exp);

    SetExp(int exp, int time);

    SetLevel(int level);

    SetLevel(int level, int time);

}; 

 

由于业务需要,我们需要一个接口 ...

 

........

 

上面的方式,有几个弊端:

 

1.接口会随着业务不断增加

2.每次更新都会更新数据源,开销比较大,如果业务需要多次更新时,不能保证原子操作

 

于是,我们想了一个办法,用一个结构体把数据封装起来,然后定义读写接口,如下所示:

 

class CCacheData

{

    struct stData{

         int id;

         string name;

         int exp;

         int level;

         int time;

    };

 

    Get(stData &data);

    Set(stData &data);

}; 

 

上面的方式业务简单而且清晰,也解决了第一种封装方式的问题,但存在安全性的问题。

比如,一个调用者,可能在业务逻辑中多次调用,在外部多次修改结构体,很有可能会不小心修改了不应该改的字段,如不小心赋了下初值等,这样set的时候会直接回写,数据就会出错。

 

于是我们想到一种更好的方式,暴露给调用者的只有接口,而数据结构本身做为一个成员变量保存在类中,如下所示:

 

class CCacheData

{

    struct stData{

         int id;

         string name;

         int exp;

         int level;

         int time;

    };

 

public: 

    Query(int id);

    Commit();

 

    SetName(string &name);

    string GetName();

 

    SetExp(int exp);

    int GetExp();

 

    SetLevel(int level);

    int GetLevel();

 

    SetTime(int time);

    int GetTime();

 

private:

    stData m_data;

}; 

 

这样,每次调用时先Query,把数据读出,并给m_data赋值,然后,可以多次调用get和set接口,如果有set过的话,最后只要调用commit接口,就可提交,这种方式有几个优点:

1.保证了原子性,无论是读或写几个字段,都只要两次操作即可完成

2.保证了类成员数据安全,封装等级比较高

3.数据结构调整时(比如添加一个flag字段),由于暴露给上层的只是接口,所以调用者代码无需修改

 

 

总结:

 

对缓存或数据库数据操作进行封装时,一定要注意原子性、通用性和可扩展性,最好给上层提供统一的接口类或实现,这样,才能保证代码不会随业务复杂性增加而快速暴涨,同时也能保证代码的清晰与易用性。

上面的封装采用了Facade模式,其实设计模式在编码中处处可以体现,这也对我们开发人员提出更高的要求,如果能合理、适度的使用设计模式,使自己的代码更简洁、更优美。

 

 

原创粉丝点击