I've used Decorator to create a Dataset class used to build a Dataset Basic Empty (ConcreteComponent) and Iris class (ConcreteDecorated) used to populate it.Decorator allows a user to add new functionality to an existing object  without altering its structureFor Example Iris has a its own way to load and store the data in dataset structure. I've added also the name features to track the string name of there features.My purpose is to add more ConcreteDecorator, like Iris, that they have a own way to load and store file/data and to track the name features. The code run, but My Doubts are: dataset is an empty table (define only the data structure) and the population depends on concrete decorator that use it. It seems to me That does not Respect the SOLID Principles (for example DIP). What do you think about this simple implementation? COMPONENTpublic interface Dataset{     public double Distanza(int i, ArrayList<Double> centroide);         public double getCella(int i, int j);    public void inizializzaTabella();       public void stampaDataset();    public void setColonna( ArrayList<Double> colonnaValori);    public ArrayList<ArrayList<Double>> getTabella();    public int getnFeature(); //ok    public int getnRecord() ;    public void setnFeature(int nFeature);     public void setnRecord(int nRecord);        public void setTabella(int Colonna, Double Valore);     public String getNomeDataset();     public void setNomeDataset(String nomeDataset);    public double[][] toMatrix();    public ArrayList<Integer> getFeatureUsate();     public void setNomiFeature(String[] nomiFeature);}CONCRETE COMPONENTpublic class DatasetConcreto implements Dataset{    private int nFeature;    private int nRecord;    private ArrayList<Integer> featureUsate; // quelle selezionate    private String nomeDataset;    private String[] nomiFeature;    //public double Tabella [][];    private ArrayList<ArrayList<Double>> Mat;    public double Distanza(int i, ArrayList<Double> centroide)    {        double Sum=0;        for(int j=0; j<nFeature; j++)            Sum+=Math.pow((centroide.get(j) - Mat.get(j).get(i)), 2);        return Math.sqrt(Sum);    }    public double getCella(int i, int j)    {        return Mat.get(j).get(i);    }    public void inizializzaTabella()    {       Mat = new ArrayList<ArrayList<Double>>();       featureUsate = new ArrayList<Integer>();       for(int i=0; i< nFeature; i++)       {           Mat.add(new ArrayList<Double>());           featureUsate.add(i); // uso tutte le feature       }    }    public void stampaDataset()    {        System.out.println(Le feature selezionate sono);        for(int j = 0; j<nFeature; j++)            System.out.println(nomiFeature[j].toString());        for(int i=0; i< nRecord; i++)        {            for(int j=0; j < nFeature; j++)            {                System.out.print( Mat.get(j).get(i)+  );            }            System.out.println(\n);        }    }    public ArrayList<Double> getRecord(int indiceRandom)    {        ArrayList<Double> record = new ArrayList<Double>();        for(int i=0; i<nFeature; i++)            record.add( Mat.get(i).get(indiceRandom));        return record;    }    public DatasetConcreto(int nFeature, String Nome)     {               setnFeature(4);        setNomeDataset(Iris.data);        inizializzaTabella();    }    public DatasetConcreto(ArrayList<ArrayList<Double>> MatInput, ArrayList<Integer> featureSelezionate, int nRecord)    {        Mat = new ArrayList<ArrayList<Double>>();        this.featureUsate = new ArrayList<Integer>(featureSelezionate);        this.nRecord = nRecord;        this.setnFeature(featureSelezionate.size());        for(int i=0; i<featureSelezionate.size(); i++)            setColonna( MatInput.get( featureSelezionate.get(i)));    }    public DatasetConcreto() {    }    public void setColonna( ArrayList<Double> colonnaValori)    {        this.Mat.add(colonnaValori);    }    public ArrayList<ArrayList<Double>> getTabella()    {        return this.Mat;    }    public int getnFeature() {        return this.nFeature;    }    public int getnRecord() {        return this.nRecord;    }    public void setnFeature(int nFeature)     {        this.nFeature = nFeature;        return;    }    public void setnRecord(int nRecord) {        this.nRecord=nRecord;        return;    }    public void setTabella(int Colonna, Double Valore)     {        Mat.get(Colonna).add(Valore);    }    public String getNomeDataset() {        return this.nomeDataset;    }    public void setNomeDataset(String nomeDataset) {         this.nomeDataset = new String(nomeDataset);    }    public double[][] toMatrix()    {        double[][] matrix = new double[this.getnRecord()][this.getnFeature()];        for(int i=0; i< nRecord; i++)        {            for(int j=0; j < nFeature; j++)            {                matrix[i][j] = Mat.get(j).get(i);            }        }        return matrix;    }    public ArrayList<Integer> getFeatureUsate()    {return this.featureUsate;}    @Override    public void setNomiFeature(String[] nomifeature)     {        this.nomiFeature = new String[nFeature];        this.nomiFeature = nomifeature;    }}DECORATORpublic abstract class DatasetDecorator implements Dataset {protected Dataset dataset;public DatasetDecorator(Dataset dataset){this.dataset=dataset;}@Overridepublic double Distanza(int i, ArrayList<Double> centroide) {    return this.dataset.Distanza(i, centroide);}@Overridepublic double getCella(int i, int j) {    return this.dataset.getCella(i, j);}@Overridepublic void inizializzaTabella() {    this.dataset.inizializzaTabella();}@Overridepublic void stampaDataset() {    this.dataset.stampaDataset();}@Overridepublic void setColonna(ArrayList<Double> colonnaValori) {    this.dataset.setColonna(colonnaValori);}@Overridepublic ArrayList<ArrayList<Double>> getTabella() {    return this.dataset.getTabella();}@Overridepublic int getnFeature() {    return this.dataset.getnFeature();}@Overridepublic int getnRecord() {        return this.dataset.getnRecord();}@Overridepublic void setnFeature(int nFeature) {    this.dataset.setnFeature(nFeature); }@Overridepublic void setnRecord(int nRecord) {    this.dataset.setnRecord(nRecord);}@Overridepublic void setTabella(int Colonna, Double Valore) {    this.dataset.setTabella(Colonna, Valore);}@Overridepublic String getNomeDataset() {    return this.dataset.getNomeDataset();}@Overridepublic void setNomeDataset(String nomeDataset) {this.dataset.setNomeDataset(nomeDataset);   }@Overridepublic double[][] toMatrix() {    return this.dataset.toMatrix();}@Overridepublic ArrayList<Integer> getFeatureUsate() {    return this.dataset.getFeatureUsate();}public void setNomiFeature(String[] nomifeature) {this.dataset.setNomiFeature(nomifeature);}}CONCRETE DECORATORpublic class Iris extends DatasetDecorator{            private final String[] nomiFeature = {LunghezzaSepalo,                                                LarghezzaSetalo,                                                 LunghezzaPetalo,                                                 LarghezzaPetalo};        public Iris(String NomeFile, Dataset dataset) throws IOException    {        super(dataset);        super.dataset.setnFeature(4);        super.dataset.setNomiFeature(nomiFeature);        super.dataset.inizializzaTabella(); //For init dataset from here                            super.dataset.setnRecord( CaricaDataset(NomeFile) );    }    protected int CaricaDataset(String pathFile) throws IOException    {        int iRecord = 0;        BufferedReader bufferLetto = null;        String line = ;        String cvsSplitBy = ,;        try {            bufferLetto = new BufferedReader(new FileReader(pathFile));            while ((line = bufferLetto.readLine()) != null)             {                if (line.length() > 0)                 {                    String[] cell = line.split(cvsSplitBy);                    this.addRow(cell);                    iRecord++;                }            }        } catch (FileNotFoundException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        } finally {            if (bufferLetto != null) {                try {                    bufferLetto.close();                } catch (IOException e) {                    e.printStackTrace();                }            }        }        return iRecord;    }    // new row    public void addRow(Object cell[])     {        System.out.println(this.nomiFeature.length);        for(int i=0; i<this.nomiFeature.length; i++)            super.dataset.setTabella(i, Double.parseDouble(cell[i].toString()));    }}   TEST CLIENTpublic class Client {    public static void main(String[] args) throws IOException     {        Dataset ds = new DatasetConcreto();        Dataset iris = new Iris(./src/Iris.data, ds);        ds.stampaDataset();    }}
Is this a correct way to use Decorator and it respect SOLID principles?
java;object oriented;design patterns