Salve. Sto cercando di capire qual è il modo migliore di creare alcuni oggetti necessari alla mia applicazione. In realtà l'app funziona già, ma da quando mi sto informando sui pattern voglio imparare a strutturare bene le cose, ed in modo pulito.

Gli oggetti in questione rappresentano tracciati e sono complicati, nel senso che per essere costruiti necessitano di svariati parametri. I tipi di tracciati sono 4:


  • Gpx
  • Road
  • TrackMarkers
  • JoinedMarkers


Nell'applicazione non può esistere un oggetto road singolarmente. Gli altri possono esistere singolarmente (non più di uno), ed eventualmente si può creare un oggetto road da abbinarci. Per intenderci road rappresenta la strada per raggiungere il tracciato, quindi è ovvio che se non è stato disegnato nessun tracciato allora non è possibile costruire un oggetto road. Detto questo, queste classi hanno del codice in comune e sostanzialmente rappresentano la stessa cosa, quindi per come le ho create ora non si sfrutta molto il riutilizzo del codice (JoinedMarkers è però molto differente dalle altre ed è molto più semplice).

Ora come ora per utilizzarli nell'Activity principale (che deve poter accedere ai dati dei tracciati costruiti) ho questi quattro oggetti come variabili private globali. Poi nel punto relativo del codice dove si richiede di crearli li inizializzo con la classica new passando i parametri necessari.

Metto ad esempio il codice di Road e TrackMarkers:

Road

codice:
public class Road {


    /** lista di coordinate */
    private List<LatLng> coordinates;


    /** lunghezza del percorso*/
    private float length;


    /** tempo di percorrenza stimato */
    private int duration;


    /** URL per la richiesta HTTP */
    private String URL;


    /** contesto dell'Activity principale */
    private Context context;


    /** timeout per la connessione */
    private int connectionTimeout;


    /** timeout per il download */
    private int dataTimeout;


    public Road(Context context, String URL, int connectionTimeout,
                int dataTimeout) {
        coordinates = new ArrayList<LatLng>();
        this.context = context;
        this.URL = URL;
        this.connectionTimeout = connectionTimeout;
        this.dataTimeout = dataTimeout;
        build();
    }


    private void build() {
        PathToTrackAsyncTask pathToTrackAsyncTask = new PathToTrackAsyncTask();
        pathToTrackAsyncTask.execute();
    }


    private class PathToTrackAsyncTask extends AsyncTask<Void, Void, String> {


        private ProgressDialog mDialog;


        protected void onPreExecute() {
            mDialog = ProgressDialog.show(context, "", "Caricamento...", true);
        }


        protected void onPostExecute(String result) {
            if(mDialog != null) {
                if(mDialog.isShowing()) {
                    mDialog.dismiss();
                }
            }


            if(result != null) {
                parseJSON(result);
            }
        }


        @Override
        protected String doInBackground(Void... params) {
            //Istanzio il JSONRequest
            JSONRequest jParser = new JSONRequest();
            //Ottengo la stringa JSON
            String json = jParser.getJSONFromUrl(URL,connectionTimeout,dataTimeout);
            //Ritorno la stringa per l'onPostExecute
            return json;
        }


        private void parseJSON(String result) {


            try {
                //Ottengo l'oggetto JSON
                final JSONObject json = new JSONObject(result);
                //Otteniamo l'array "routes" dall'oggetto json
                JSONArray routeArray = json.getJSONArray("routes");
                //Prendo il primo (ed unico) risultato
                JSONObject routes = routeArray.getJSONObject(0);
                //Ottengo l'array legs per la lunghezza e tempo di percorrenza
                JSONArray legsArray = routes.getJSONArray("legs");
                //Estraggo l'oggetto contenuto in legsArray
                JSONObject legsObject = legsArray.getJSONObject(0);
                //Estraggo lunghezza e tempo di percorrenza
                JSONObject distanceObject = legsObject.getJSONObject("distance");
                JSONObject durationObject = legsObject.getJSONObject("duration");
                //Ottengo un oggetto che possiede un array di punti codificati che rappresentano
                //il percorso approssimato
                JSONObject overviewPolylines = routes.getJSONObject("overview_polyline");
                //Ottengo la stringa dei punti codificati
                String encodedString = overviewPolylines.getString("points");
                //Decodifico la stringa per ottenere una lista di LatLng
                ArrayList<LatLng> res = Utilities.getInstance().decodePoly(encodedString);
                coordinates.addAll(res);


                length = distanceObject.getInt("value");
                duration = durationObject.getInt("value");
            }
            catch (JSONException e) {
                e.printStackTrace();
                Toast.makeText(context, "Il percorso non è disponibile", Toast.LENGTH_SHORT).show();
            }
        }
    }


    public float getLength() {
        return length;
    }


    public int getDuration() {
        return duration;
    }


    public List<LatLng> getCoordinates() {
        return coordinates;
    }
}
TrackMarkers

codice:
public class TrackMarkers {


    /** lunghezza del tracciato */
    private float length;


    /** elevazione media */
    private double averageElevation;


    /** modalità di viaggio */
    private String travelMode;


    /** lista di coordinate del tracciato */
    private List<LatLng> coordinates;


    /** lista di markers per costruire il percorso */
    private List<Marker> markers;


    /** tempo di percorrenza stimato **/
    private int duration;


    /** contesto dell'Activity principale */
    private Context context;


    /** timeout per la connessione */
    private int connectionTimeout;


    /** timeout per il download */
    private int dataTimeout;


    /** flag per il calcolo della lunghezza */
    private boolean flag;


    public TrackMarkers(Context context, String travelMode, List<Marker> markers,
        int connectionTimeout, int dataTimeout) {


        flag = false;
        this.travelMode = travelMode;
        this.markers = markers;
        this.context = context;
        this.connectionTimeout = connectionTimeout;
        this.dataTimeout = dataTimeout;
        coordinates = new ArrayList<LatLng>();
        //avvia la costruzione del tracciato
        build();
        //calcola la lunghezza del tracciato risultante
        calculatesLength();
    }


    private void build() {
        for(int i = 0; i < markers.size() - 1; i++) {
            Marker firstMarker = markers.get(i);
            Marker secondMarker = markers.get(i + 1);
            //I extract latitude and longitude from the markers
            LatLng firstLatLng = new LatLng(firstMarker.getPosition().latitude, firstMarker.getPosition().longitude);
            LatLng secondLatLng = new LatLng(secondMarker.getPosition().latitude, secondMarker.getPosition().longitude);


            //Ogni volta si costruisce un URL aggiornato per la nuova coppia di markers
            String URL = Utilities.getInstance().makeURL(firstLatLng.latitude, firstLatLng.longitude,
                    secondLatLng.latitude, secondLatLng.longitude, travelMode);


            if(i == markers.size() - 2) {
                flag = true;
            }


            MultipleTracksAsyncTask multipleTracksAsyncTask = new MultipleTracksAsyncTask(URL);
            multipleTracksAsyncTask.execute();
        }
    }


    private class MultipleTracksAsyncTask extends AsyncTask<Void,Void,String> {


        private ProgressDialog mDialog;
        private String URL;


        public MultipleTracksAsyncTask(String URL) {
            this.URL = URL;
        }


        protected void onPreExecute() {
            mDialog = ProgressDialog.show(context, "", "Loading...", true);
        }


        protected void onPostExecute(String result) {
            if(mDialog != null) {
                if(mDialog.isShowing()) {
                    mDialog.dismiss();
                }
            }
            //effettuo il parsing del JSON
            if(result != null) {
                parseJSON(result);
                //se la computazione è finita, calcola la lunghezza
                if(flag) {
                    calculatesLength();
                }
            }
        }


        public String doInBackground(Void... param) {
            JSONRequest jParser = new JSONRequest();
            String json = jParser.getJSONFromUrl(URL,connectionTimeout,dataTimeout);
            return json;
        }
    }


    private void parseJSON(String result) {
        try {
            final JSONObject json = new JSONObject(result);


            JSONArray routeArray = json.getJSONArray("routes");
            JSONObject routes = routeArray.getJSONObject(0);
            JSONArray legsArray = routes.getJSONArray("legs");


            JSONObject legsObject = legsArray.getJSONObject(0);
            JSONObject distanceObject = legsObject.getJSONObject("distance");
            JSONObject durationObject = legsObject.getJSONObject("duration");
            JSONObject overviewPolylines = routes.getJSONObject("overview_polyline");


            String encodedString = overviewPolylines.getString("points");
            ArrayList<LatLng> list = Utilities.getInstance().decodePoly(encodedString);
            coordinates.addAll(list);


            length += distanceObject.getInt("value");
            duration += durationObject.getInt("value");


        } catch (JSONException e) {
            e.printStackTrace();
            Toast.makeText(context, "The path is not available", Toast.LENGTH_SHORT).show();
        }
    }


    private void calculatesLength() {
        for(int i=0; i < coordinates.size() - 1; i++) {
            LatLng firstLatLng = coordinates.get(i);
            LatLng secondLatLng = coordinates.get(i+1);
            length += Utilities.getInstance().getDistance(firstLatLng,secondLatLng);
        }
    }


    public float getLength() {
        return length;
    }


    public double getAverageElevation() {
        return averageElevation;
    }


    public int getDuration() {
        return duration;
    }


    public List<LatLng> getCoordinates() {
        return coordinates;
    }
}
Forse dovrei utilizzare uno dei pattern che ho scritto nel titolo, o addirittura unire Factory Method e Template Method, ma non so, sono ancora inesperto sul capire quale utilizzare e come.