Design patterns 什么样的设计模式可以容纳大量不可交换的对象?

Design patterns 什么样的设计模式可以容纳大量不可交换的对象?,design-patterns,singleton,pool,Design Patterns,Singleton,Pool,我正在为这个场景寻找一个好的设计模式: 我有一堆硬件设备,每个都由C++库中的一个类来表示(我们称之为类设备)。使用该库的计算机会为每个设备打开一个UDP套接字(它们由我的网络中的IP标识)。库和设备之间的通信是通过JSON消息进行的。因此,库通过套接字发送和接收JSON对象 库所做的第一件事是发现设备的数量,请求一个包含该信息的JSON对象(基本上是每个设备的IP)。然后,构建一个包含所有设备对象的向量 这可以看作是一个对象池,因为最后我有一组设备对象,每个对象封装了一个网络连接。但是它们不能

我正在为这个场景寻找一个好的设计模式:

我有一堆硬件设备,每个都由C++库中的一个类来表示(我们称之为类设备)。使用该库的计算机会为每个设备打开一个UDP套接字(它们由我的网络中的IP标识)。库和设备之间的通信是通过JSON消息进行的。因此,库通过套接字发送和接收JSON对象

库所做的第一件事是发现设备的数量,请求一个包含该信息的JSON对象(基本上是每个设备的IP)。然后,构建一个包含所有设备对象的向量

这可以看作是一个对象池,因为最后我有一组设备对象,每个对象封装了一个网络连接。但是它们不能互换。在数据库连接池中,我可以选择一个对象并使用它连接数据库。但如果我需要向特定设备发送消息,我需要该设备对象。别再有一个了

类的原始创建者将其建模为一个包含向量的单例。因为我们只需要一个入口点来访问设备对象的向量。但我认为这是事实


有更好的方法来模拟这个类吗?

我不会把这个集合称为一个集合。拥有一个对象池的目的是减少同一类型的多个实例的实例化成本,允许客户机在使用资源池后将资源“返回”到该池。您的设备不能透明地交换,并且收集点与资源使用完全无关

我想到了两种方法:

  • 您可以使用
    map
    使用其唯一键(例如
    std::map
    )快速获取某个
    设备
    ,但您可能更清楚地知道使用什么作为键而不是普通字符串),类似于:

    // find the right device instance
    string deviceInfo = "some-unique-key";
    Device device = devicesMap.find(deviceInfo)->second;
    
    // send the data
    string json = serialize(dataObject);
    device.send(json);
    
    另一方面,您可能希望将实际(反)序列化委托给
    设备本身,以防某些设备的协议可能不同:

    // find the right device instance
    string deviceInfo = "some-unique-key";
    Device device = devicesMap.find(deviceInfo)->second;
    
    // send the object, Device class will know how to serialize it
    device.send(dataObject);
    
  • 另一个有趣的选择是将消息发送到所有
    设备
    实例,让它们决定消息是否与它们相关(基于您认为合适的内容)。这种方法允许多个设备可以发送相同的消息(如果他们愿意),或者只需在不发送任何消息的情况下通知发生了什么:

    // notify all devices that we have a message
    for (auto &device : devicesVector) {
    
        // you are only notifying the device.
        // each instance should decide whether or not to
        // pass the message forward (based on its contents),
        // and how to serialize it
    
        device.notify(dataObject);
    }
    
  • 您当前的实现是单例的这一事实是另一个问题。Singleton是一种创造性模式,与对象的生命周期有关,通常仅用于避免传递依赖关系。它稍微简化了ctor签名,但也可能涉及到一些惰性,特别是考虑到您使单元测试变得更加困难这一事实


    Proper将要求您将此服务显式地传递给所有使用者(通常是彻底的构造函数注入),这将减少耦合,从而允许更轻松的单元测试。这并不意味着您需要重构整个代码以使用DI容器,只需将处理通信的“thingy”通过其构造函数传递给调用方即可。

    我不会将此集合称为DI容器。拥有一个对象池的目的是减少同一类型的多个实例的实例化成本,允许客户机在使用资源池后将资源“返回”到该池。您的设备不能透明地交换,并且收集点与资源使用完全无关

    我想到了两种方法:

  • 您可以使用
    map
    使用其唯一键(例如
    std::map
    )快速获取某个
    设备
    ,但您可能更清楚地知道使用什么作为键而不是普通字符串),类似于:

    // find the right device instance
    string deviceInfo = "some-unique-key";
    Device device = devicesMap.find(deviceInfo)->second;
    
    // send the data
    string json = serialize(dataObject);
    device.send(json);
    
    另一方面,您可能希望将实际(反)序列化委托给
    设备本身,以防某些设备的协议可能不同:

    // find the right device instance
    string deviceInfo = "some-unique-key";
    Device device = devicesMap.find(deviceInfo)->second;
    
    // send the object, Device class will know how to serialize it
    device.send(dataObject);
    
  • 另一个有趣的选择是将消息发送到所有
    设备
    实例,让它们决定消息是否与它们相关(基于您认为合适的内容)。这种方法允许多个设备可以发送相同的消息(如果他们愿意),或者只需在不发送任何消息的情况下通知发生了什么:

    // notify all devices that we have a message
    for (auto &device : devicesVector) {
    
        // you are only notifying the device.
        // each instance should decide whether or not to
        // pass the message forward (based on its contents),
        // and how to serialize it
    
        device.notify(dataObject);
    }
    
  • 您当前的实现是单例的这一事实是另一个问题。Singleton是一种创造性模式,与对象的生命周期有关,通常仅用于避免传递依赖关系。它稍微简化了ctor签名,但也可能涉及到一些惰性,特别是考虑到您使单元测试变得更加困难这一事实


    Proper将要求您将此服务显式地传递给所有使用者(通常是彻底的构造函数注入),这将减少耦合,从而允许更轻松的单元测试。这并不意味着您需要重构整个代码以使用DI容器,只需将处理通信的“thingy”通过其构造函数传递给调用方即可。

    我不会将此集合称为DI容器。拥有一个对象池的目的是减少同一类型的多个实例的实例化成本,允许客户机在使用资源池后将资源“返回”到该池。您的设备不能透明地交换,并且收集点与资源使用完全无关

    我想到了两种方法:

  • 您可以使用
    map
    使用其唯一键(例如
    std::map
    )快速获取特定的
    设备