English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Cet article présente un exemple de modèle de programmation Android: le modèle Builder. Partageons-le avec vous pour que vous puissiez en bénéficier, voici les détails:
Un, introduction
Le modèle Builder est un modèle de création qui crée un objet complexe étape par étape, qui permet à l'utilisateur de contrôler plus finement le processus de construction de l'objet sans connaître les détails internes de la construction. Ce modèle vise à dé耦é le processus de construction d'un objet complexe de ses composants, de sorte que le processus de construction et la représentation des composants soient isolés.
Parce qu'un objet complexe a de nombreuses composantes, par exemple, une voiture a des roues, un volant, un moteur, et diverses petites pièces, etc., comment assembler ces composants pour former une voiture, ce processus d'assemblage est long et complexe. Dans ce cas, pour cacher les détails de l'implémentation externe pendant le processus de construction, on peut utiliser le modèle Builder pour séparer les composants et le processus d'assemblage, de sorte que le processus de construction et les composants puissent être étendus librement, et la couplage entre eux est réduit au minimum.
Deux, la définition
Séparer la construction d'un objet complexe de son représentation, de sorte que le même processus de construction puisse créer différentes représentations.
Trois, les scénarios d'utilisation
(1Lorsque la même méthode, avec un ordre d'exécution différent, produit des résultats d'événements différents.
(2Lorsque plusieurs composants ou pièces peuvent être assemblés dans un objet, mais que les résultats de l'exécution ne sont pas les mêmes.
(3Lorsque la classe de produit est très complexe, ou lorsque l'ordre d'appel dans la classe de produit est différent et produit des effets différents, dans ce cas, l'utilisation du modèle Builder est très appropriée.
(4Lorsque l'initialisation d'un objet est particulièrement complexe, par exemple, avec de nombreux paramètres et de nombreux paramètres avec des valeurs par défaut.
Quatre, le diagramme UML du modèle Builder
Présentation des rôles :
Classe Produit - classe abstraite du produit;
Builder - classe Builder abstraite, normalise la composition du produit, généralement implémentée par les sous-classes pour réaliser le processus de composition spécifique;
ConcreateBuilder - classe Builder spécifique;
Director - processus d'assemblage unifié;
Cinquième partie : implémentation simple du modèle Builder
Le processus d'assemblage de l'ordinateur est relativement complexe et l'ordre d'assemblage n'est pas fixe. Pour faciliter la compréhension, nous simplifions le processus d'assemblage de l'ordinateur en construire le hôte, configurer le système d'exploitation, configurer l'écran3composants individuels, puis les assemble par l'intermédiaire du Director et du Builder spécifique pour construire l'objet de l'ordinateur.
Exemple de code :
/** * classe Computer abstraite, rôle de Produit */ public abstract class Computer { protected String mBoard; protected String mDisplay; protected String mOS; protected Computer(){} /** * configurer la carte mère * @param board */ public void setBoard(String board){ this.mBoard = board; } /** * configurer l'écran * @param display */ public void setDisplay(String display){ this.mDisplay = display; } /** * Set operating system */ public abstract void setOS(); @Override public String toString(){ return "Computer [mBoard=" + mBoard + ", mDisplay=" + mDisplay + ", mOS=" + mOS + "]"; } }
/** * classe Computer spécifique, Macbook */ public class Macbook extends Computer { protected Macbook(){} @Override public void setOS() { mOS = "Mac OS X 10"; } }
/** * classe Builder abstraite */ public abstract class Builder { /** * configurer le hôte * @param board */ public abstract void buildBoard(String board); /** * configurer l'écran * @param display */ public abstract void buildDisplay(String display); /** * Set operating system */ public abstract void buildOS(); /** * Create Computer * @return */ public abstract Computer create(); }
/** * Specific Builder class, MacbookBuilder */ public class MacbookBuilder extends Builder { private Computer mComputer = new Macbook(); @Override public void buildBoard(String board) { mComputer.setBoard(board); } @Override public void buildDisplay(String display) { mComputer.setDisplay(display); } @Override public void buildOS() { mComputer.setOS(); } @Override public Computer create() { return mComputer; } }
/** * Director class, responsible for constructing Computer */ public class Director { Builder mBuilder = null; public Director(Builder builder){ mBuilder = builder; } /** * Build object * @param board Motherboard * @param display Display */ public void construct(String board, String display){ mBuilder.buildBoard(board); mBuilder.buildDisplay(display); mBuilder.buildOS(); } }
/** * Test code */ public class Test { public static void main(String[] args){ //Builder Builder builder = new MacbookBuilder(); //Director Director pcDirector = new Director(builder); //Encapsulation construction process pcDirector.construct("Intel motherboard","Retina display"); //Construire un ordinateur, afficher les informations pertinentes System.out.println("Computer Info : ", + builder.create().toString()); } }
Résultat de la sortie :
Computer Info : Computer [mBoard=Intel motherboard, mDisplay=Retina display, mOS=Mac OS X 10]
Dans cet exemple, le MacbookBuilder spécifique est utilisé pour construire l'objet Macbook, et Director encapsule le processus de construction complexe de l'objet produit, en cachant les détails de construction. Builder et Director séparent la construction d'un objet complexe de son représentation, ce qui permet de créer des objets différents avec le même processus de construction.
Il est important de noter que dans le processus de développement réel, le rôle de Director est souvent omis. On utilise directement un Builder pour assembler des objets, généralement en mode appel en chaîne. Le point clé est que chaque méthode setter retourne soi-même, c'est-à-dire return this, ce qui permet d'appeler les méthodes setter en chaîne. Le code est approximativement le suivant :
new TestBuilder() .setA("A") .create();
De cette manière, non seulement le rôle de Director est supprimé, mais l'architecture est également plus simple, et on a un contrôle plus fin sur le processus de composition de l'objet Product.
Sixième variante du modèle Builder - Appel en chaîne
Exemple de code :
public class User { private final String name; //obligatoire private final String cardID; //obligatoire private final int age; //optionnel private final String address; //optionnel private final String phone; //optionnel 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); } } }
Points à noter :
Le constructeur de la classe User est privé, les appelants ne peuvent pas créer directement d'objet User.
Les attributs de la classe User sont immuables. Tous les attributs ont été ajoutés avec le modificateur final, et leurs valeurs ont été définies dans le constructeur. De plus, seules les méthodes getters sont fournies en externe.
Le constructeur de la classe interne Builder accepte uniquement les paramètres obligatoires, et ces paramètres obligatoires utilisent le modificateur final.
Méthode d'appel :
new User.UserBuilder("Jack","10086) .age(25) .address("GuangZhou") .phone("13800138000") .build();
Compared to the previous ones through the constructor and setter/Deux méthodes pour les getters, avec une meilleure lisibilité. Le seul problème potentiel pourrait être la création de multiples objets Builder, ce qui consomme de la mémoire. Cependant, dans la plupart des cas, notre classe interne Builder utilise le modificateur statique (static), donc ce problème n'est pas si important.
À propos de la sécurité des threads
Le modèle Builder n'est pas thread-safe. Si vous devez vérifier la légalité d'un paramètre à l'intérieur de la classe interne Builder, il est nécessaire de le faire après la création complète de l'objet.
正确示例:
public User build() { User user = new user(this); if (user.getAge() > 120) { throw new IllegalStateException("Age out of range"); // 线程安全 } 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("Button",1", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { //TODO } }); builder.setNegativeButton("Button",2", 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();
Il est visible que dans l'utilisation réelle, le rôle de Director est omis, dans la plupart des codes sources des cadres, lorsque le modèle Builder est utilisé, ce n'est pas le modèle classique GOF du Builder, mais plutôt le modèle plus simple.
Huit, avantages et inconvénients
Avantages :
Bonne encapsulation, qui rend le client inutile de connaître les détails de la mise en œuvre interne du produit
Indépendance du constructeur, forte extensibilité
Inconvénients :
Création de multiples objets Builder, Director, consommation de mémoire
Les lecteurs intéressés par plus de contenu sur Android peuvent consulter les sujets spéciaux de ce site : "Introduction et avancement des tutoriels de développement Android", "Résolution des problèmes courants et techniques de débogage Android", "Résumé des utilisations des composants de base Android", "Résumé des techniques des vues View Android", "Résumé des techniques de layout Android" et "Résumé des utilisations des contrôles Android"
J'espère que les informations fournies dans cet article pourront aider les développeurs Android.
Déclaration : Le contenu de cet article est issu du réseau, propriété des auteurs originaux, le contenu est apporté par les utilisateurs d'Internet et téléversé spontanément, ce site Web ne détient pas de propriété, n'a pas été traité par l'éditeur humain et n'assume aucune responsabilité juridique connexe. Si vous trouvez du contenu suspect de violation de copyright, veuillez envoyer un e-mail à : notice#w3Déclaration : Le contenu de cet article est issu du réseau, propriété des auteurs originaux, le contenu est apporté par les utilisateurs d'Internet et téléversé spontanément, ce site Web ne détient pas de propriété, n'a pas été traité par l'éditeur humain et n'assume aucune responsabilité juridique connexe. Si vous trouvez du contenu suspect de violation de copyright, veuillez envoyer un e-mail à : notice#w