dimanche 16 juin 2019

Is this a proper way to share variables among many objects without a singleton?

So, I have a program where many objects of several different classes need to read some (many) variables from an object of 'class X', to give it a name. A quick and simple way of doing this would be to make a singleton, which wouldn't be X itself but a class it access to. I've done this, and later on it started feeling dirty, and many seem to agree, so I'd like to change my design for this. I haven't found any ideas to replace this pattern, though, just "don't do it" and "pass the data around." I'd like my data to be read-only, though. I haven't found mention of any other patterns.

The best I've got to share these read-only variables, which seems perfectly fine to me, is to have a class SharedVars for the data to share, but in the form of an inner class. It's inside Data, which is an outer class that is able to modify SharedVars, encapsulating what's meant to be read-only for the other classes. Basically, any class that wants to read these variables needs a Data.SharedVars object:

    public class Data {
        public static class SharedVars {
            private int encapsulatedData;

            public int getData() {
                return encapsulatedData;
            }       
        }

        // no one should touch this but Data:
        private SharedVars sharedData; 

        Data() {
            sharedData = new SharedVars();
        }

        public SharedVars getDataRef() {
            return sharedData;
        }

        // here's where this class (and only this class, whenever it's told)
        // modifies the encapsulated data:
        void manipulateData() {
            sharedData.encapsulatedData = 5;
        }
    }

One of the classes that depends on this would take this form:

     public class Client {
        // This class can't access the data directly
        // so it'll use Data's getter:
        Data.SharedVars vars;

        public Client(Data.SharedVars vars) {
            this.vars = vars;
            // vars.encapsulatedData = 5; // is not allowed, since the field is private (which is what I want)
        }

        public void go() {
            // the proper way to get its hand on the data:
            int data = vars.getData();
            System.out.println("The data is " + data);
        }
    }

Main is not needed in this example, but I'll leave it here anyway:

public class Main {
    static Data dataControl;
    static Client client;

    public static void main(String[] args) {
        dataControl = new Data();
        client = new Client(dataControl.getDataRef());

        dataControl.manipulateData();
        client.go();
    }

}

Is this proper? Or, what are the risks here? Notice I don't want the objects to copy them for themselves, since they'll be changing all the time, and I don't entirely like the idea of having a reference to the 'class X' I've mentioned before.

Aucun commentaire:

Enregistrer un commentaire