mercredi 12 avril 2023

How to create a container for data of different types in Java?

I'm trying to figure out what is the right Java code structure of a feature written in JavaScript.

I have several classes each of them should handle its method calls and store related data. Each class processes data for different ids (some kind of containerId). Data values are of different types:

// javascript
class A {
  constructor() {
    this._containers = new Map();
  }

  method1(id, data) {
    // ensure that a container for <id> exists
    const container = this._containers.get(id);
    container.set('hello', 'world');
  }

  method2(id, data) {
    // ensure that a container for <id> exists
    const container = this._containers.get(id);
    container.set('prop', 1);
  }

  method3(id, data) {
    const container = this._containers.get(id); // in this case no need to ensure
    container.set('some', 1.0);
  }
}

class B {
  constructor() {
    this._containers = new Map();
  }

  method1(id, data) {
    // ensure that a container for <id> exists
    const container = this._containers.get(id);
    container.put({ prop1: 'value1', prop2: 0 }); // this is actually not allowed in js, pseudo-code
  }
}

I'd like to remove code duplication (and also the responsibility of data storing management) with composition. Moving all store logic in a separate class, e.g. DataHolder. I just want to call dataHolder.add(containerId, key, value); which will check that a container exists and add key, value to it.

Java DataHolder could have an underlying storage as a Map<String, ?>. Due to method overloading I could define different variations of an add method:

// java
public class DataHolder {
  private Map<Integer, Map<String, ?>> containers = new HashMap<>();
  // ...
  add(int containerId, String key, ? value) {}
  add(int containerId, ? value) {} // it could take container.size() as a key
}

How do I define this ? in DataHolder so that it handles everything correctly. If it's an Object how does A class know which type a value is? instanceof seems a bad idea. (When an A instance decides that it got the last chunk of data it should create a new Record for example with collected values).

If it's not the way a Java code is written, so what is the way?

Another approach could be to create AContainers class which holds a map of A instances (for each id) with all fields defined inside A class. But I don't like this approach because in that case AContainers should proxy all method calls to A instance (and also have some knowledge when A is done). For each algorithm A, B, ..., Z there will be 1 additional class. (2*N classes instead of N). And it should anyway implement the logic of creating an A instance on event (which contradicts the initial intent to move the creation logic outside the processors).

Aucun commentaire:

Enregistrer un commentaire