Come creare un wrapper API pubblico con diversi parametri di configurazione

1

Sto cercando di vedere se esiste un modello di progettazione in grado di risolvere il seguente problema. L'esempio è abbastanza specifico ma l'obiettivo è un'API pubblica + interna. Ho bisogno di informazioni specifiche per la mia biblioteca sottostante, ma voglio presentare l'API genericamente. Se la mia domanda è vaga o terribile, cercherò di farlo con i tuoi commenti.

Ad esempio, diciamo che sto creando un'API pubblica e voglio che sia agnostico all'implementazione. Continuando con l'esempio, sto creando un'API di gestione del lavoro che utilizza la libreria Quartz (può essere qualsiasi libreria) nell'attuale implementazione.

Voglio che le persone siano in grado di digitare:

Job job = jobManager.getJob("my.job.name");
String otherInformation = job.getOtherInformation();
job.setSchedule(new IntervalSchedule(repeatInterval, intervalUnit));
job.setSchedule(new CronSchedule(cronExpression));

L'API Quartz ha builder per le pianificazioni (utilizzate in Trigger):

CronScheduleBuilder.cronSchedule(cronExpression);
CalendarIntervalBuilder.calendarIntervalSchedule()
                       .withInterval(repeatInterval, 
                           DateBuilder.IntervalUnit.DAY);

Nel mio esempio attuale avrei un'interfaccia di base o un programma di classe. Con questa struttura, come sarebbe possibile ottenere le informazioni specifiche di cui ho bisogno per i costruttori di programmi senza rivelare un oggetto specifico di implementazione nella mia interfaccia pur mantenendolo estendibile. Il mio obiettivo è impedire che le classi di implementazione filtrino nell'API pubblica. Se in futuro il quarzo cade in disgrazia, l'API pubblica non ha bisogno di cambiare e deprecare le classi specifiche del quarzo. Quale modello di progettazione o riorganizzazione del codice mi manca?

    
posta cldfzn 14.01.2014 - 20:54
fonte

1 risposta

1

Una buona soluzione qui sarebbe il schema di fabbrica astratto . Essenzialmente, c'è una fabbrica di base astratta con una serie di metodi astratti per costruire determinate classi astratte. Quindi, forniresti una sottoclasse concreta di questa fabbrica che implementa i metodi per una determinata libreria. Prendi questo esempio:

public class ScheduleCreator {
    public abstract AbstractSchedule makeSchedule();
}

Quindi avresti un'implementazione specifica per ogni libreria che ti serve:

public class QuartzScheduleCreator extends ScheduleCreator {
    @Override
    public AbstractSchedule makeSchedule() {
        return new QuartzSchedule(); // where QuartzSchedule extends AbstractSchedule
    }
}

Quindi il client, utilizzando un astratto ScheduleCreator, non avrebbe bisogno di conoscere la libreria che fornisce l'implementazione dietro le quinte:

public void scheduleEvent(ScheduleCreator creator) {
    AbstractSchedule schedule = creator.makeSchedule();
    schedule.schedule(new Event());
}

In seguito, se decidi di cambiare la tua implementazione da Quartz a una libreria diversa (chiamiamola Foo), devi semplicemente creare un nuovo FooScheduleCreator che restituisca un'istanza di FooSchedule quando chiama makeSchedule (). Quindi potresti fornire ScheduleCreator al metodo senza che il Cliente debba preoccuparsi di quale libreria funzioni sotto il cofano:

scheduleEvent(new FooScheduleCreator()); // if you want the client to use Foo
scheduleEvent(new QuartzScheduleCreator()); // if you want the client to use Quartz

Naturalmente, ogni ScheduleCreator può avere molti più metodi per qualsiasi cosa tu abbia bisogno.

    
risposta data 07.07.2014 - 19:41
fonte

Leggi altre domande sui tag