Quale pattern dovrei usare per factory + wrapper

2

Devo programmare un client generico che utilizzi diversi client concreti (diverse API), tutti che condividono la stessa interfaccia. Devo registrare la risposta del client.

Per fare ciò (eseguendo il login in background senza che l'utente debba eseguirlo manualmente), ho creato queste classi:

Request , Response , ClientService , Client1 , Client2 , ClientInterface .

Quindi, istanziate ClientService e impostate il nome del cliente, ad esempio:

$client = $this->get('clientService')->setClient('client1');

// $data is an associative array
$request = $client->createRequest($data); 

// $response was saved to database by ClientService, before returning it.
$response = $client->doRequest($request); 

ClientService , Client1 e Client2 implementa ClientInterface , che ha metodi doRequest() , createRequest() , getError() , ecc., ma tutte le implementazioni di ClientService fanno inoltrare la richiesta al cliente reale .

Ho fatto questo per poter salvare automaticamente la risposta al database, e affinché ciò avvenga senza dover ripetere il codice in tutti i client, e per lasciare che questa preoccupazione sia nel servizio, doveva avere il controllo sull'intero ciclo di vita richiesta / risposta.

Mi chiedo se esiste uno schema che descrive già questo scenario.

    
posta JorgeeFG 14.12.2016 - 02:19
fonte

2 risposte

1

In base a ciò che stai mostrando, la classe Client gestisce le richieste, la risposta, l'accesso al database e praticamente tutto, è una classe Blob che è un pattern anti. Quindi il mio suggerimento è:

  1. Utilizza alcuni pattern come MVC MVP o altro per gestire la richiesta.
  2. Delega l'accesso al tuo database utilizzando il pattern DAO, magari con pdo o un record attivo.
  3. ClientService dovrebbe agire solo sul livello aziendale, avvolgere diverse chiamate al database e astrarre il DAL. Pertanto dovrebbe implementare l'interfaccia Client .
  4. Definisci una buona implementazione di ereditarietà, se davvero necessaria, per le classi Client1 e Client2 , e in base a ciò stabilisci il modello db. Ciò si illuminerà se è necessaria un'implementazione diversa del modello di accesso al database di tua scelta.

Si noti che questo è completamente basato su ciò che hai pubblicato, forse con più codice, potremmo essere più utili.

    
risposta data 15.12.2016 - 08:23
fonte
1

Ho creato un pattern / implementazione che chiamo AdaptiveClient. Il codice è troppo lungo per postare qui. Puoi leggerlo sul mio sito web o scaricare su < a href="https://github.com/leaderanalytics/AdaptiveClient"> github .

Proprio come la tua domanda descrive, AdaptiveClient restituisce un client che implementa un'interfaccia richiesta. Quindi se vuoi chiamare un metodo come doRequest(request) e farlo eseguire sul server ottimale che è attualmente disponibile puoi farlo in questo modo:

public class HomeController : Controller
{
    private IAdaptiveClient<IUsersService> client;

    public HomeController(IAdaptiveClient<IUsersService> client)
    {
        this.client = client;
    }

    public async Task<IActionResult> DoSomething(int userID)
    {
        // use an in-process connection to the database if its available otherwise use
        // whatever server is available to handle the request (WebAPI, WCF, etc.):
        Request request = // whatever request is
        SomeThing thing = await client.CallAsync(x => x.doRequest(request));
    }
}

Nel codice sopra, AdaptiveClient restituisce un'implementazione concreta di un'interfaccia di esempio IUsersService .

AdaptiveClient consente di architettare la tua applicazione come livello n e accedere alla tua API su LAN o sul Web, se necessario.

    
risposta data 29.01.2017 - 22:47
fonte