Classe di fabbrica rispetto a una classe statica

0

Ho un piccolo problema nella scelta del miglior design. Ho alcune (5 al momento) operazioni di elaborazione delle immagini nel mio coe (Java). Ogni fase di elaborazione indipendente dalle altre e consoistica di una piccola quantità di codice, 5-15 linee in generale. Questi sono principalmente wrapper per JAI, AWT e così via.

Il mio attuale design è una classe astratta:

public abstract class AbstractPreProcessingStep {
    protected Logger logger = Logger.getLogger(this.getClass().getName());

    protected AbstractPreProcessingStep() {
    };

    public abstract BufferedImage startProcessing(BufferedImage input);

}

Ogni fase di elaborazione implementa questa classe e può essere definita uniforme. (come il modello di strategia).

Poiché ogni fase di elaborazione può avere un diverso set di parametri, ho creato una classe factory, come questa:

public class PreProcessingFactory {


    public static AbstractPreProcessingStep createColorInverter() {
        return new ColorInverter();
    }


    public static AbstractPreProcessingStep createRescaler(float rescaleFactor) {
        return new Rescaler(rescaleFactor);
    }


    public static AbstractPreProcessingStep createEdgeDetector() {
        return new EdgeDetector();
    }

    public static AbstractPreProcessingStep createBlackAndWhite() {
        return new BlackAndWhite();
    }
...

Quindi, se vuoi creare un'immagine in bianco e nero con colori invertiti, devi farlo (codice pseude)

bw = PreProcessingFactory.createBlackAndWhite();
inv = PreProcessingFactory.createInverter();
result = bw.startProcessing(result);
result = inv.startProcessing(result);

Nella mia mente, questo è un buon progetto poiché i dettagli di implementazione sono nascosti e le nuove fasi di elaborazione possono essere facilmente aggiunte aggiungendo una nuova classe.

L'altro approccio che avevo in mente era quello di creare una singola classe con ogni passo come metodo statico - tuttavia, non mi piace "static"

Hai qualche suggerimento per migliorare il codice?

    
posta Mirco 17.07.2013 - 12:37
fonte

2 risposte

0

Stai promuovendo termini.

Il problema non è Classe di fabbrica rispetto alla classe statica , ma un metodo per ogni processo rispetto a una classe per ogni processo .

Il "metodo di una classe per ogni processo" che sembra prendere in considerazione presenta molti vantaggi, principalmente flessibilità e scalabilità.

Tuttavia, per implementarlo, dovrai utilizzare una specie di Pattern creativo per aiutarti a mantenere il codice disgiunto dalle lezioni concrete.

L'approccio di classe Factory che stai utilizzando è OK.

L'ordine o il modo in cui chiami questi processi è una questione di Pattern comportamentali come Chain of Responsability, Iterator, State, Command ecc. Questi pattern comportamentali sono usati per disaccoppiare il richiedente (la classe che deve chiamare un processo) dalla classe concreta che effettivamente fa il lavoro.

    
risposta data 17.07.2013 - 18:44
fonte
2

Farò le seguenti ipotesi sul tuo processo:

  1. Un passaggio non ha bisogno di conoscere il funzionamento interno di un altro passo.
  2. L'ordine di questi passaggi è significativo (non ottieni gli stessi risultati eseguendo queste operazioni nell'ordine opposto).

In questa situazione, posso solo dirti veramente cosa farei. Eviterei il pattern Factory, semplicemente perché implica che devi avere un metodo factory per ogni tipo di fase, e se volessi inventare nuove fasi, dovresti anche modificare la fabbrica. Inoltre, anche se potrebbe essere gestibile in pezzi di dimensioni ridotte, se dovessi affrontare 50 fasi, anche se non fosse cambiato spesso, sarebbe comunque molto complicato. Per non parlare del fatto che la fabbrica sembrerebbe implicare che l'ordine è irrilevante. Ti fa pensare che puoi fare un numero qualsiasi di AbstractPreProcessingStep se applicarli nell'ordine che desideri. Anche se questo non è il caso, penso che sia generalmente meglio presentare un'interfaccia che non sia fuorviante per un programmatore.

Considera il seguente modello alternativo: Catena di responsabilità

Supponete di avere un AbstractProcessor di classe come tale:

public abstract class AbstractProcessor {
    protected AbstractProcessor step;

    public void setNextStep(AbstractProcessor step) {
        this.step = step;
    }

    public abstract BufferedImage process(BufferedImage input);
}

Quindi potresti avere i tuoi passi in questo modo:

public class ColorInverter extends AbstractProcessor {
    public ColorInverter(AbstractProcessor step) {
        setNextStep(step);
    }

    public BufferedImage process(BufferedImage input) {
        // Perform color inverter process here
        return step != null ? step.process(output) : output;
    }
}
public class Rescaler extends AbstractProcessor {
    public Rescaler(AbstractProcessor step) {
        setNextStep(step);
    }

    public BufferedImage process(BufferedImage input) {
        // Perform rescalar process here
        return step != null ? step.process(output) : output;
    }
}

Proprio così, è bello nella sua semplicità, tuttavia, è possibile sovrascrivere l'ordinamento per i passaggi che devono essere eseguiti alla fine semplicemente chiamando " step.process(input) " ed eseguendo qualche operazione sul risultato restituito.

Inoltre, se esistessero fasi specifiche, potresti sostituire la AbstractProcessor di setNextStep per richiedere un determinato tipo di AbstractProcessor per garantire che vengano raggiunte determinate fasi. Prendi ad esempio il seguente:

public abstract class RasteringProcessingStep extends AbstractProcessor { 
    public void setNextStep(RasteringProcessingStep step) {
        super.setNextStep(step);
    }
    public void setNextStep(PostProcessingStep step) {
        super.setNextStep(step);
    }
}

In questo modo, assicuri che qualsiasi passaggio che implementa RasteringProcessingStep debba essere seguito da un altro RasteringProcessingStep o deve essere seguito da un PostProcessingStep che deriva anche da AbstractPreProcessingStep .

Per usarlo, vedresti qualcosa di simile:

AbstractProcessor processor = new ColorInverter(new Rescaler(null));
File image = new File("strawberry.jpg");
BufferedImage output = processor.process(ImageIO.read(image));

Per favore fatemi sapere cosa ne pensate di questo approccio.

    
risposta data 17.07.2013 - 17:53
fonte

Leggi altre domande sui tag