Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 18
  1. #1

    Instantiate Concrete class in Abstract Static method

    La cosa e' contorta, ma un esempio sara illuminante:

    codice:
    abstract class AbstractClass{
     private Object innerData;
     public Object acces method(){
       //qualcosa 
     } 
     public abstract void altro metoco();
    
     public static AbstractClass creaIstanza(){
       return new "concrete class istance"; //vorrei creare un istanza della classe che implementa questa classe astratta 
     } 
    }
    e' possibile ?

  2. #2
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,328
    Ovvio che sì.
    E' quello che viene fatto dal pattern Factory.

    Un esempio classico è la classe Calendar: è abstract e contiene dei metodi statici (esempio, getInstance() ) che ne ritornano una implementazione concreta.


    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  3. #3
    Ho dato un occhiata a Calendar, e forse non mi sono spiegato bene:

    codice:
    abstract class AbstractClass{
     private Object innerData;
     public Object acces method(){
       //qualcosa 
     } 
     public abstract void altro metoco();
    
     public static AbstractClass creaIstanza(){
       return new "concrete class istance"; //vorrei creare un istanza della classe che implementa questa classe astratta 
     } 
    }
    
    class ConcreteClassA extends AbstractClass{
      @Override
      public void altro metoco(){
         ;//qualcosa
      }
    }
    
    class ConcreteClassB extends AbstractClass{
      @Override
      public void altro metoco(){
         ;//qualcosa
      }
    }
    
    //da qualche parte...
    void main(){
      ConcreteClassB cb = ConcreteClassB.creaIstanza();
      ConcreteClassA ca = ConcreteClassA.creaIstanza();
    
    //cb contiene un oggetto di tipo ConcreteClassB mentre ca uno di tipo ConcreteClassA (instanziati con il costruttore di default delle 2 classi concrete)
    }
    Calendar instanzia le classi concrede conoscendone il nome, io invece vorrei istanziare la classe concreta di cui al momento non conosco nulla, so solo che avra un costruttore di default. Al momento ho risolto creando il metodo creaIstanza() in ogni singola classe concreta:

    codice:
    class ConcreteClassA extends AbstractClass{
      @Override
      public void altro metoco(){
         ;//qualcosa
      }
      public static AbstractClass creaIstanza(){
        return new ConcreteClassA();
      }
    }
    C'e' un evidente duplicazione di codice, mentre sarebbe sufficiente cambiare il nome del costruttore della classe concreta. (ovviamente non e' solo questo...non creo un istanza ogni volta che viene chiamato il metodo, ma gestisco un pipe, quindi il codice duplicato aumenta)

  4. #4
    Se la classe ConcreteClassA estende la classe astratta AbstractClass e ne implementa i metodi astratti allora ti basta fare una new:

    codice:
    ConcreteClassA ca = new ConcreteClassA();
    non capisco il tuo problema. Se hai esigenze diverse facci sapere. Oppure spiega esattamente il comportamento che desideri ottenere e vediamo se la strategia che stai adottando è quella opportuna.
    "Mai discutere con un idiota. Ti trascina al suo livello e ti batte con l'esperienza." (Oscar Wilde)

  5. #5
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,328
    Originariamente inviato da lelmarir
    Calendar instanzia le classi concrede conoscendone il nome, io invece vorrei istanziare la classe concreta di cui al momento non conosco nulla, so solo che avra un costruttore di default.
    Quello che chiedi non ha alcun senso: se c'è più di una classe concreta, quale dovrebbe essere istanziata? Che poi, il metodo che hai usato non ti consente di evitare di conoscere il nome della classe...

    Mi sembra ovvio che tu debba conoscere il nome della classe che andrai ad istanziare.

    Davvero, non riesco a capire quale sia il problema...


    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  6. #6
    ok, allora passo a spiegarvi cosa devofare concretamente:

    Ho una classe astratta, ItemFactory che implementa in modo generico l'accesso a un database e il caching dei dati letti

    Poi vengono create classi derivate come ad esempio ArticoliFactory e FattureFactory che sfruttando le funzionalita offerte da ItemFactory e modificandone la configurazione recuperano i dati dal database.

    A questo punto ArticoliFactory e' una sorta di DataSurce e per istanziarlo e' sufficiente

    ArticoliFactory a = new ArticoliFactory();

    il problema e' che questa classe viene usata da piu parti del codice e ognuna in questo modo si creerebbe una sua istanza e quindi si potrebbero avere gli stessi dati duplicati.

    la cosa migliore sarebbe che ogni volta che serve si potesse chiamare :

    ArticoliFactory a = ArticoliFactory.createInstance();

    dove solo la prima volta viene creata concretamente un istanza (e memorizzata) e tutte le successive viene restituita sempre la stessa istanza (che a questo punto potrebbe essere gia popolata e pronta a restituire i dati senza causare altre richieste al database)

    Per il momento ho risolto implementando createInstance() in ogni singola classe concreta, ma mi sembra strano che una funzionalita del genere non si possa implementare a livello della classe astratta.

    Spero di essere stato piu chiaro questa volta e di aver fatto capire qual'e' il mio scopo.

    metto anche il codice:

    JDCItemsFactory.java
    codice:
    package it.lelmarir.inventario4.data;
    
    import it.lelmarir.db.JDCConnection;
    import it.lelmarir.db.JDCConnectionDriver;
    
    import java.io.Serializable;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    import java.util.LinkedList;
    import java.util.List;
    
    import com.google.gwt.dev.protobuf.GeneratedMessage.ExtendableBuilder;
    import com.vaadin.data.util.ItemsFactory;
    import com.vaadin.data.util.SqlConstraint;
    import com.vaadin.data.util.SqlConstraintBlock;
    
    public abstract class JDCItemsFactory[B] implements ItemsFactory[B], Serializable{
    	
    	private String queryFields = "a.*,c.testo AS nomeCategoria";
    	private String queryTable = "articolo a LEFT JOIN codcategoria c ON a.id_categoria = c.id";
    	private String querySort = "";
    	SqlConstraintBlock constraints = new SqlConstraintBlock();
    	
    	public JDCItemsFactory(String queryFields, String queryTable) {
    		this.queryFields = queryFields;
    		this.queryTable = queryTable;
    	}
    	
    	@Override
    	public void addContainerFilter(Object propertyId, String filterString, boolean ignoreCase, boolean onlyMatchPrefix) {
    		constraints.addConstraint((new SqlConstraint(propertyId.toString())).like(((onlyMatchPrefix)?"%":"")+filterString));
    		//TODO: ignoreCase
    	}
    	
    	@Override
    	public List[B] getItems(int startIndex, int count) {
    		List[B] list = new LinkedList[B]();
    		JDCConnection connection = JDCConnectionDriver.getConnection();		
    		String query = "";
    		try {
    			Statement stm = connection.createStatement();
    		
    			String cond = constraints.getSqlConstraint();
    			query = "SELECT "+queryFields+" FROM "+queryTable+" "+ ((cond!="")?" WHERE "+cond:"") + ((querySort!="")?"ORDER BY "+querySort:"") +" LIMIT "+startIndex+","+count;
    			ResultSet result = stm.executeQuery(query);
    			while(result.next() == true)
    			{				
    				list.add(resultSetToBean(result));
    			}
    		} catch (SQLException e) {
    			System.err.println(this.getClass().getName() + ":" + query);
    			e.printStackTrace();
    		}
    		
    		return list;
    	}
    	
    	protected abstract B resultSetToBean(ResultSet resultSet);
    	
    	@Override
    	public abstract Class[B] getType();
    	
    	@Override
    	public void removeAllContainerFilters() {
    		constraints.removeAllConstraints();
    		
    	}
    	
    	@Override
    	public void removeContainerFilters(Object propertyId) {
    		constraints.removeConstraint(propertyId.toString());		
    	}
    	
    	@Override
    	public int size() {		
    		try {
    			JDCConnection connection = JDCConnectionDriver.getConnection();		
    			Statement stm = connection.createStatement();
    			
    			String cond = constraints.getSqlConstraint();
    			String query = "SELECT count(*) AS count FROM "+queryTable+ ((cond!="")?" WHERE "+cond:"");
    			ResultSet result = stm.executeQuery(query);
    	
    			if(result.next() == true)
    			{
    				return result.getInt("count");
    			}
    		} catch (SQLException e) {
    			e.printStackTrace();
    		}
    		
    		return 0;
    		
    	}
    	
    	public void sort(Object[] propertyId, boolean[] ascending) {
    		querySort = "";
    		
    		if(propertyId.length == 0)
    			return;		
    		
    		querySort += propertyId[0].toString() + " " + ((ascending[0])?"DESC":"");
    		for(int i = 1; i < propertyId.length; i++)
    		{
    			querySort += ", ";
    			querySort += propertyId[i].toString() + " " + ((ascending[i])?"DESC":"");
    		}
    		
    	}
    }
    ArticoloItemFactory.java
    codice:
    package it.lelmarir.inventario4.data;
    
    import it.lelmarir.db.JDCConnection;
    import it.lelmarir.db.JDCConnectionDriver;
    
    import java.io.Serializable;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    import java.util.LinkedList;
    import java.util.List;
    
    import org.eclipse.jdt.internal.compiler.ast.ThisReference;
    
    import com.vaadin.data.util.ItemsFactory;
    import com.vaadin.data.util.SqlConstraint;
    import com.vaadin.data.util.SqlConstraintBlock;
    
    public class ArticoloItemFactory extends JDCItemsFactory<Articolo> implements
    		Serializable {
    
    	private static ArticoloItemFactory instance = null;
    	public static ArticoloItemFactory createInstance(){
    		if(instance == null)
    			instance = new ArticoloItemFactory();
    		return instance;
    	}
    	
    	public ArticoloItemFactory() {
    		super("a.*,c.testo AS nomeCategoria",
    				"articolo a LEFT JOIN codcategoria c ON a.id_categoria = c.id");
    	}
    
    	@Override
    	protected Articolo resultSetToBean(ResultSet resultSet) {
    		try {
    			return new Articolo(resultSet.getString("id"), 
    					resultSet.getString("nome"), 
    					resultSet.getString("descrizione"),
    					resultSet.getString("posizione"), 
    					resultSet.getDouble("prezzo"), 
    					resultSet.getDouble("coefficientePrezzo"), 
    					resultSet.getDouble("prezzoFinito"), 
    					resultSet.getInt("id_categoria"), 
    					resultSet.getString("nomeCategoria"));
    		} catch (SQLException e) {
    			e.printStackTrace();
    		}
    		return null;
    	}
    
    	@Override
    	public Class<Articolo> getType() {
    		return Articolo.class;
    	}
    }
    Se a qualcuno interessa pubblico anche le altre classi necessarie a far funzionare il tutto

  7. #7
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,328
    Da quello ceh ho capito mi sembra che tu stia cercando di implementare il pattern Singleton (che non ha nulla a che vedere con la concretezza o l'astrattezza delle classi).

    Ti pongo una domanda: non ti è sufficiente qualcosa di questo tipo?

    codice:
    public class ArticoliFactory ... {
       private ArticoliFactory istanzaPrivata;
       ...
       public static ArticoliFactory getInstance() {
          if (istanzaPrivata == null) {
             // E' la prima richiesta: creo l'istanza
             istanzaPrivata = new ArticoliFactory( ... );
          }
          return istanzaPrivata;
       }
    }
    Tutte le classi richiamano "getInstance()", ma solo la prima volta verrà effettivamente creata una nuova istanza... tutte le altre volte, l'istanza restituita sarà quella creata la prima volta.

    Oppure continuo a non capire quale sia il problema...


    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  8. #8
    difatti e' quello che ho ora:

    codice:
    private static ArticoloItemFactory instance = null;
    	public static ArticoloItemFactory createInstance(){
    		if(instance == null)
    			instance = new ArticoloItemFactory();
    		return instance;
    	}
    Mi chiedevo se era possibile implementare la stessa cosa a livello JDCItemsFactory per rendere ancora più semplici tutte le classi derivate

  9. #9
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,328
    Originariamente inviato da lelmarir
    difatti e' quello che ho ora:

    Mi chiedevo se era possibile implementare la stessa cosa a livello JDCItemsFactory per rendere ancora più semplici tutte le classi derivate
    Uhm... si può fare in questo modo (solo, non so se è la soluzione più adatta):

    codice:
    public abstract class JDCItemsFactory ... {
       private JDCItemsFactory articoliFactory;
       private JDCItemsFactory altraFactory;
       private JDCItemsFactory ancoraAltraFactory;
       ...
       public static JDCItemsFactory getArticoliFactory() {
          if (articoliFactory == null) articoliFactory = new ArticoliFactory();
          return articoliFactory;
       }
    
       public static JDCItemsFactory getAltraFactory() {
          if (altraFactory == null) altraFactory = new AltraFactory();
          return altraFactory;
       }
    
       public static JDCItemsFactory getAncoraAltraFactory() {
          if (ancoraAltraFactory == null) ancoraAltraFactory = new AncoraAltraFactory();
          return ancoraAltraFactory;
       }
    }
    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  10. #10
    Originariamente inviato da LeleFT
    Da quello ceh ho capito mi sembra che tu stia cercando di implementare il pattern Singleton (che non ha nulla a che vedere con la concretezza o l'astrattezza delle classi).

    Ti pongo una domanda: non ti è sufficiente qualcosa di questo tipo?

    codice:
    public class ArticoliFactory ... {
       private ArticoliFactory istanzaPrivata;
       ...
       public static ArticoliFactory getInstance() {
          if (istanzaPrivata == null) {
             // E' la prima richiesta: creo l'istanza
             istanzaPrivata = new ArticoliFactory( ... );
          }
          return istanzaPrivata;
       }
    }
    Tutte le classi richiamano "getInstance()", ma solo la prima volta verrà effettivamente creata una nuova istanza... tutte le altre volte, l'istanza restituita sarà quella creata la prima volta.

    Oppure continuo a non capire quale sia il problema...


    Ciao.
    Credo anche io che la soluzione alle sue esigenze sia un singleton. L'unico appunto al codice da te postato è quello di inserire un costruttore private altrimenti è possibile istanziare oggetti di tipo ArticoliFactory tramite new invocando il costruttore vuoto di default il che deve essere evitato. Il costrutture privato permette di evitare questa cosa:

    codice:
    public class ArticoliFactory ... {
       private ArticoliFactory istanzaPrivata;
       ...
    
       private ArticoliFactory( ... ) {
       }
    
       ...
       public static ArticoliFactory getInstance() {
          if (istanzaPrivata == null) {
             // E' la prima richiesta: creo l'istanza
             istanzaPrivata = new ArticoliFactory( ... );
          }
          return istanzaPrivata;
       }
    }
    "Mai discutere con un idiota. Ti trascina al suo livello e ti batte con l'esperienza." (Oscar Wilde)

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.