English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Questo articolo descrive l'esempio di design pattern Builder nel programming Android. Condividiamo con tutti per riferimento, come segue:
Uno, introduzione
Il modello Builder è un modello di creazione che crea un oggetto complesso passo per passo, che permette all'utente di controllare più finemente il flusso di costruzione dell'oggetto senza conoscere i dettagli di costruzione interni. Questo modello è progettato per decouplare il processo di costruzione dell'oggetto e le sue parti, rendendo il processo di costruzione e la rappresentazione delle parti separate.
Poiché un oggetto complesso ha molte parti componenti, ad esempio, un'auto ha ruote, volante, motore e vari piccoli componenti, come assemblare queste parti in un'auto, il processo di assemblaggio è molto lungo e complesso. In questo caso, per nascondere i dettagli di implementazione esterni durante il processo di costruzione, si può utilizzare il modello Builder per separare le parti e il processo di assemblaggio, rendendo il processo di costruzione e le parti liberi di espandersi e riducendo al minimo la dipendenza tra i due.
Due, definizione
Separare la costruzione di un oggetto complesso dalla sua rappresentazione, rendendo possibile creare rappresentazioni diverse con lo stesso processo di costruzione.
Tre, scenari di utilizzo
(1) La stessa metodologia, diverso ordine di esecuzione, produce risultati di eventi diversi.
(2) Molte parti o componenti possono essere assemblati in un oggetto, ma i risultati di esecuzione prodotti non sono diversi.
(3) La classe prodotto è molto complessa o l'ordine di chiamata diverso produce effetti diversi, in questo caso è molto appropriato utilizzare il modello Builder.
(4) Quando l'inizializzazione di un oggetto è particolarmente complessa, come molti parametri e molti parametri hanno valori predefiniti.
Quattro, diagramma UML del modello Builder
Introduzione ai ruoli:
Product classe prodotto - classe astratta del prodotto;
Builder - classe astratta Builder, che standardizza la costruzione del prodotto, di solito implementata da sottoclassi per realizzare il processo di costruzione specifico;
ConcreateBuilder - classe Builder specifica;
Director - processo di assemblaggio unificato;
Cinque, implementazione semplice del modello Builder
Il processo di assemblaggio del computer è piuttosto complesso e l'ordine di assemblaggio non è fisso. Per facilitarne la comprensione, abbiamo semplificato il processo di assemblaggio del computer in tre parti: costruzione del sistema principale, configurazione del sistema operativo, configurazione del display, quindi costruiamo l'oggetto computer attraverso il Director e il Builder specifico.
Esempio di codice:
/** * Classe astratta di computer, ossia il ruolo di Product */ public abstract class Computer { protected String mBoard; protected String mDisplay; protected String mOS; protected Computer(){} /** * Imposta la motherboard * @param board */ public void impostaBoard(String board){ this.mBoard = board; } /** * Imposta il display * @param display */ public void impostaDisplay(String display){ this.mDisplay = display; } /** * Imposta il sistema operativo */ public abstract void impostaOS(); @Override public String toString(){ return "Computer [mBoard=" + mBoard + ", mDisplay=" + mDisplay + ", mOS=" + mOS + "]"; } }
/** * La classe Computer specifica, Macbook */ public class Macbook extends Computer { protected Macbook(){} @Override public void impostaOS() { mOS = "Mac OS X 10"; } }
/** * La classe Builder astratta */ public abstract class Builder { /** * Imposta la motherboard * @param board */ public abstract void costruireBoard(String board); /** * Imposta il display * @param display */ public abstract void costruireDisplay(String display); /** * Imposta il sistema operativo */ public abstract void costruireOS(); /** * Crea Computer * @return */ public abstract Computer crea(); }
/** * La classe Builder specifica, MacbookBuilder */ public class MacbookBuilder extends Builder { private Computer mComputer = new Macbook(); @Override public void costruireBoard(String board) { mComputer.setBoard(board); } @Override public void costruireDisplay(String display) { mComputer.setDisplay(display); } @Override public void buildOS() { mComputer.setOS(); } @Override public Computer create() { return mComputer; } }
/** * La classe Director, responsabile della costruzione di Computer */ public class Director { Builder mBuilder = null; public Director(Builder builder){ mBuilder = builder; } /** * Costruzione dell'oggetto * @param board Scheda madre * @param display Display */ public void construct(String board, String display){ mBuilder.buildBoard(board); mBuilder.buildDisplay(display); mBuilder.buildOS(); } }
/** * Codice di test */ public class Test { public static void main(String[] args){ // Costruttore Builder builder = new MacbookBuilder(); // Director Director pcDirector = new Director(builder); // Incapsulamento del processo di costruzione pcDirector.construct("scheda madre Intel","display Retina"); // Costruzione del computer, output delle informazioni System.out.println("Info Computer: " + builder.create().toString()); } }
Risultato di output:
Info Computer: Computer [mBoard=scheda madre Intel, mDisplay=display Retina, mOS=Mac OS X 10]
Nell'esempio sopra, attraverso il MacbookBuilder specifico per costruire l'oggetto Macbook, il Director incapsula il processo di costruzione di oggetti prodotti complessi, nascondendo i dettagli di costruzione. Il Builder e il Director separano la costruzione di un oggetto complesso dalla sua rappresentazione, permettendo che lo stesso processo di costruzione crei oggetti diversi.
È importante notare che nel processo di sviluppo reale, il ruolo di Director viene spesso omesso. Si utilizza direttamente un Builder per l'assemblaggio degli oggetti, che di solito è una chiamata a catena. Il punto chiave è che ogni metodo setter restituisce se stesso, ossia return this, il che rende possibile la chiamata a catena dei metodi setter. Il codice è più o meno il seguente:
new TestBuilder() .setA("A") .create();
Questo tipo di forma non solo elimina il ruolo di Director, ma rende anche la struttura più semplice e offre un controllo più fine sul processo di assemblaggio dell'oggetto Product.
Variante del modello Builder - chiamate a catena
Esempio di codice:
public class User { private final String name; //obbligatorio private final String cardID; //obbligatorio private final int age; //opzionale private final String address; //opzionale private final String phone; //opzionale private User(UserBuilder userBuilder){ this.name=userBuilder.name; this.cardID=userBuilder.cardID; this.age=userBuilder.age; this.address=userBuilder.address; this.phone=userBuilder.phone; } public String getName() { return name; } public String getCardID() { return cardID; } public int getAge() { return age; } public String getAddress() { return address; } public String getPhone() { return phone; } public static class UserBuilder{ private final String name; private final String cardID; private int age; private String address; private String phone; public UserBuilder(String name,String cardID){ this.name=name; this.cardID=cardID; } public UserBuilder age(int age){ this.age=age; return this; } public UserBuilder address(String address){ this.address=address; return this; } public UserBuilder phone(String phone){ this.phone=phone; return this; } public User build(){ return new User(this); } } }
Punti da notare:
Il costruttore della classe User è privato, i chiamanti non possono creare direttamente l'oggetto User.
Le proprietà della classe User sono immutabili. Tutte le proprietà sono aggiunte con il modificatore final (final) e sono impostate nel costruttore. E solo metodi getters sono forniti all'esterno.
Il costruttore della classe interna Builder accetta solo i parametri obbligatori e questi parametri obbligatori utilizzano il modificatore final (final).
Modo di chiamata:
new User.UserBuilder("Jack","10086") .age(25) .address("GuangZhou") .phone("13800138000") .build();
Confronto a costruttore e metodi setter/getter precedenti, la leggibilità è maggiore. L'unico problema potenziale potrebbe essere la creazione di oggetti Builder aggiuntivi, che consumano memoria. Tuttavia, nella maggior parte dei casi, la classe interna Builder utilizza il modificatore statico (static), quindi questo problema non è così grave.
Sulla sicurezza thread
Il modello Builder non è thread-safe. Se si desidera verificare la legittimità di un parametro all'interno della classe interna Builder, è necessario controllarla dopo la creazione dell'oggetto.
Esempio corretto:
public User build() { User user = new user(this); if (user.getAge() > 120) { throw new IllegalStateException("Età fuori dall'intervallo"); // Sicurezza thread } return user; }
错误示例:
public User build() { if (age > 120) { throw new IllegalStateException("Age out of range"); // 非线程安全 } return new User(this); }
七、用到Builder模式的例子
1、Android中的AlertDialog.Builder
private void showDialog(){ AlertDialog.Builder builder=new AlertDialog.Builder(context); builder.setIcon(R.drawable.icon); builder.setTitle("Title"); builder.setMessage("Message"); builder.setPositiveButton("Button1", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { //TODO } }); builder.setNegativeButton("Button2", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { //TODO } }); builder.create().show(); }
2、OkHttp中OkHttpClient的创建
OkHttpClient okHttpClient = new OkHttpClient.Builder() .cache(getCache()) .addInterceptor(new HttpCacheInterceptor()) .addInterceptor(new LogInterceptor()) .addNetworkInterceptor(new HttpRequestInterceptor()) .build();
3、Retrofit中Retrofit对象的创建
Retrofit retrofit = new Retrofit.Builder() .client(createOkHttp()) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .baseUrl(BASE_URL) .build();
In pratica, nel funzionamento reale, il ruolo di Director è stato omesso. In molti codici sorgente di framework, quando si tratta di modello Builder, la maggior parte non è il modello Builder classico GOF, ma ha scelto il modello più semplice.
otto, pro e contro
Vantaggio:
Buona encapsulazione, che rende il client non necessitato di conoscere i dettagli dell'implementazione interna del prodotto
Il costruttore è indipendente e ha una forte capacità di espansione
Svantaggio:
Generazione di oggetti Builder e Director in eccesso, consumo di memoria
Per chi è interessato a ulteriori contenuti relativi a Android, i lettori possono consultare le sezioni speciali di questo sito: 'Tutorial di introduzione e avanzamento di Android', 'Trucchi di debug e soluzioni ai problemi comuni di Android', 'Sommarizzazione dell'uso dei componenti di base di Android', 'Sommarizzazione delle tecniche di View di Android', 'Sommarizzazione delle tecniche di layout di Android' e 'Sommarizzazione dell'uso dei controlli di Android'.
Spero che questo articolo possa essere utile per la progettazione di applicazioni Android.
Dichiarazione: il contenuto di questo articolo è stato tratto da Internet, il copyright è di proprietà del rispettivo proprietario, il contenuto è stato contribuito e caricato autonomamente dagli utenti di Internet, questo sito non detiene i diritti di proprietà, non è stato elaborato manualmente e non assume responsabilità legali correlate. Se trovi contenuti sospetti di violazione del copyright, ti preghiamo di inviare una e-mail a: notice#oldtoolbag.com (al momento dell'invio dell'e-mail, sostituisci # con @) per segnalare, fornendo prove pertinenti. Una volta verificata, questo sito eliminerà immediatamente il contenuto sospetto di violazione del copyright.