• 如何在模块中共享数据


      在与业务逻辑相关的模块中,不同的类之间共享一些数据是再平常不过的事啦。在前两年的程序员生涯中,我主要采用过两种方式:

    使用数据管理类

         我所在公司的应用程序框架使用的是MVC三层架构,由于历史原因,每个模板都由一个Model,一个controller加上一系列的View组成,所有要共享的数据都存在Model中,Model提供setter和访问接口:

         SetObject(int  nObjectID,Object*pObject);

         Object*GetObject(int  nObjectID);

        这样,如果你要共享一个自定义的对象,拿AddressBook来说吧你需要做如下事情:

        1)  从Object继承下来;

             class AddressBook:public Object

             {…};

        2) 调用setter方法存储数据:

            m_pModel->SetObject(ID_ADDRESS_BOOK,newAddressBook);

        3)  使用共享数据:

        AddressBook * pObject = (AddressBook *)m_pModel->GetObject(ID_ADDRESS_BOOK);

       这个方法的优点:

        1)  简单;

        2)  数据封闭在同一模块,在其他模块访问到本模块数据的可能性不大。

       缺点如下:

       1)   在Model,View,Controller之外模块其他部分很难得到这些共享数据,而它们本来应该是对整个模块可见的。要在其他部分得到这些共享数据,必须得将model设置进去;

       2)   如果要多线程访问,就会比较地麻烦;

       3)   不是类型安全的。

    使用Singleton模式

        我也曾经思考过将共享数据用一个单例来管理,但是好像从逻辑上来说,这些数据不是整个应用程序所有,而是一个模块所有,而且基本上也只能弥补第一种方法的第一个缺陷。代价是整个应用程序中到处充斥着这种单例。所以我不认为这种方法可取。

    由于没有找到什么好的方法,所以我当时决定还是用第一种方案,不过内心总有个疙瘩。 直到前几天,我发现了一个更好的方法,拿出来共享一下.

    用对象标识+引用计数方案

          首先看一下在这种方案下如何共享数据是有益处的:

      1) 申明要共享的对像:

        SharedDataHolder<AddressBook> m_strAddress(“Address book”,aAddrBook);

      2) 使用共享对象:

       ShareDataHolder<AddressBook>aAddressBook(“Address book”);

       aAddressBook->somemethod();

      很简单吧。使用和申明是可以分开的,你可以在不引入任何依赖的情况下使用这些数据!!!而且申明和使用大同小异。

      好了,现在可以看一下是如何实现的。

      每一个共享数据都有一个id,用什么都行,只要能唯一地标识一个对象就成,对象在第一次出现时,会将自己注册到一个std::map中。以后在要使用这个数据只是增加引用计数而已。

      在下面这个示例的实现中主要包含两个类:

      1)StorePolicy. 这是个类模板Policy(如果你对这种技巧不是十分地熟,你可真要仔细研究一下《C++ Template》这本书啦),其用途是定义各种类型的存储格式:内置类型,真接存值,自定义类型,存指针。同时它还得提供类型的默认值和消毁方法。

      2)SharedDataHolder:应用程序主要应该和它打交道,它有一个类静态变量g_oSharedDatabase用来保存共享的数据,保存在其中的对象都是引用计数的,在引用计数为0时被销毁。你可以通过3种方法来申明一个共享对象,因为它定义了3个构造函数(你也可以加上赋值函数等等)。

              对于基本数据类型,可以调用它的 value方法得到其值。

              对于自定义类型,你可以像指针一样使用对象

          源代码如下:

    代码
    #ifndef _SHAREDSTOREPOLICY_H
    #define _SHAREDSTOREPOLICY_H

    template
    <typename T>
    struct StorePolicy
    {
    typedef T
    * StoreType;
    static StoreType getDefaultValue()
    {
    return new T();
    }

    static StoreType getDefaultValue(const T& rCopy)
    {
    return new T(rCopy);
    }

    static void destroyValue(StoreType pData)
    {
    delete pData;
    }

    static T& getValue(StoreType pData)
    {
    return *pData;
    }
    };

    #define MAKE_FUNADTION_STORE_POLICY(type) \
    template
    <> \
    struct StorePolicy<type> \
    { \
    typedef type StoreType; \
    static StoreType getDefaultValue() \
    { \
    return StoreType(); \
    } \
    static StoreType getDefaultValue(StoreType rCopy) \
    { \
    return StoreType(rCopy); \
    } \
    static void destroyValue(StoreType pData) \
    { \
    } \
    static type& getValue(StoreType& pData) \
    { \
    return pData; \
    } \
    };

    MAKE_FUNADTION_STORE_POLICY(
    bool)
    MAKE_FUNADTION_STORE_POLICY(
    char)
    MAKE_FUNADTION_STORE_POLICY(signed
    char)
    MAKE_FUNADTION_STORE_POLICY(unsigned
    char)
    MAKE_FUNADTION_STORE_POLICY(wchar_t)

    MAKE_FUNADTION_STORE_POLICY(signed
    short)
    MAKE_FUNADTION_STORE_POLICY(unsigned
    short)
    MAKE_FUNADTION_STORE_POLICY(signed
    int)
    MAKE_FUNADTION_STORE_POLICY(unsigned
    int)
    MAKE_FUNADTION_STORE_POLICY(signed
    long)
    MAKE_FUNADTION_STORE_POLICY(unsigned
    long)

    #if LONGLONG_EXISTS
    MAKE_FUNADTION_STORE_POLICY(signed
    long long)
    MAKE_FUNADTION_STORE_POLICY(unsigned
    long long)
    #endif //LONGLONG_EXISTS

    MAKE_FUNADTION_STORE_POLICY(
    float)
    MAKE_FUNADTION_STORE_POLICY(
    double)
    MAKE_FUNADTION_STORE_POLICY(
    long double)

    #undef MAKE_FUNADTION_STORE_POLICY
    #endif
    代码
    #ifndef _SHAREDDATAHOLDER_HPP
    #define _SHAREDDATAHOLDER_HPP
    #include
    <string>
    #include
    <map>
    #include
    <utility>
    #include
    "SharedStorePolicy.h"

    template
    <typename T>
    class SharedDataHolder
    {
    public:
    typedef typename StorePolicy
    <T>::StoreType StoreDataType;
    typedef std::pair
    <int,StoreDataType> DatabaseItemType;
    SharedDataHolder(
    const std::string& strKey):
    m_strKey(strKey)
    ,m_rData(g_oSharedDatabase[strKey])
    {

    if (0 == g_oSharedDatabase[m_strKey].first)
    {
    g_oSharedDatabase[m_strKey].second
    = StorePolicy<T>::getDefaultValue();
    }
    ++m_rData.first;
    }

    SharedDataHolder(
    const std::string& strKey,const T& rData):
    m_strKey(strKey)
    ,m_rData(g_oSharedDatabase[strKey])
    {
    if (0 == g_oSharedDatabase[strKey].first)
    {
    g_oSharedDatabase[m_strKey].second
    = StorePolicy<T>::getDefaultValue(rData);
    }
    ++m_rData.first;
    }

    SharedDataHolder(
    const SharedDataHolder& rhs):
    m_strKey(rhs.m_strKey)
    ,m_rData(rhs.m_rData)
    {
    ++m_rData.first;
    }

    ~SharedDataHolder( void )
    {
    if (0 == --m_rData.first)
    {
    StorePolicy
    <T>::destroyValue(m_rData.second);
    g_oSharedDatabase.erase(g_oSharedDatabase.find(m_strKey));
    }
    }

    public:
    StoreDataType
    operator->( void )
    {
    return m_rData.second;
    }
    const StoreDataType operator->( void )const
    {
    return m_rData.second;
    }

    T
    & operator*( void )
    {
    return StorePolicy<T>::getValue(m_rData.second);
    }

    const T& operator*( void )const
    {
    return StorePolicy<T>::getValue(m_rData.second);
    }

    T
    & value( void ) {return StorePolicy<T>::getValue(m_rData.second);}
    const T& value( void )const {return StorePolicy<T>::getValue(m_rData.second);}
    private:
    std::
    string m_strKey;
    DatabaseItemType
    & m_rData;
    static std::map<std::string,DatabaseItemType> g_oSharedDatabase;
    };

    template
    <typename T>
    std::map
    <std::string,typename SharedDataHolder<T>::DatabaseItemType> SharedDataHolder<T>::g_oSharedDatabase ;
    #endif

      这个方法的优点是:

      1) 很方便就可以在模块中共享数据;

      2) 有多线程时,可以比较方便地现对这些共享数据读写;

      3) 是类型安全的;

      4) 简单。

        缺点也是有的:

         1) 使用了全局变量;

         2) 对数据的保护力度不够,在其他模块也可以到这些数据,这也许不算个缺点,因为我们需要在不同的模块之间传递数据。

        扩展:

         1)StorePolicy对于枚举类型也应该采用存值的方式;

      2) 在SharedDataHolder中加上更多的方法(比如赋值,== ,!=等);

      3)同步ShareDataHolder多线程读写操作.

  • 相关阅读:
    Android 编程代码手机定位
    Android 编程下快捷图标的创建
    Android 编程技巧设置 ADB 连接超时时间
    Android 编程下获得应用程序的签名
    Android 编程下如何获取有 Internet 访问权限的应用
    Android 编程下通知的发送
    Androidpn 消息推送总结
    Json 和 Jsonlib 的使用
    asp.net 控件不显示,提示无法找到
    做一课永远成长的苹果树!
  • 原文地址:https://www.cnblogs.com/li_shugan/p/1901641.html
Copyright © 2020-2023  润新知