Le modèle de conception (modèle de conception) est un ensemble de résumés classifiés et catalogués de l'expérience de conception de code utilisé à plusieurs reprises et connu de la plupart des gens.
Les modèles de conception sont divisés en trois types, avec un total de 23 types :
Écrit en référence à des articles dans Hongyang, des didacticiels Rookie, etc. Veuillez me corriger s'il y a des erreurs. S'il y a une infraction, veuillez me contacter pour la supprimer.
1. Modèle de conception Modèle d'observateur (Modèle d'observateur) Prenant le service public WeChat comme exemple
2. Design Pattern Factory Pattern (Factory Pattern) commence par la vente de Roujiamo
3. Analyse complète du modèle de conception Singleton (modèle Singleton)
4. Modèle de conception Le modèle de stratégie (Strategy Pattern) prend les jeux de rôle comme arrière-plan
5. Modèle de conception Modèle d'adaptateur (Modèle d'adaptateur) Prenons l'exemple du chargeur de téléphone portable
6. Modèle de commande de modèle de conception pour gérer les appareils électroménagers intelligents
7. Design Pattern Decorator Pattern vous ramène au monde légendaire
8. Mode conception, mode apparence (Motif de façade) mode film en un clic
9. Le modèle de méthode de modèle de conception montre la journée d'un programmeur
10. Modèle d'état de modèle de conception (modèle d'état) Prenons un distributeur automatique comme exemple
11. Modèle de conception Modèle de constructeur (Modèle de constructeur) Prenons l'exemple de la construction d'une voiture et de l'achat d'une voiture.
12. Modèle de conception Modèle de prototype (Modèle de prototype) Prenons l'exemple de l'obtention de plusieurs formes
13. Le modèle de conception Flyweight Pattern (Flyweight Pattern) prend comme exemple l'obtention aléatoire de plusieurs formes.
14. Modèle de proxy de modèle de conception (modèle de proxy) Prenons l'exemple de l'obtention d'images à partir du disque
15. Modèle de conception Modèle de pont (Modèle de pont) Prenons comme exemple le dessin de cercles de différentes couleurs
16. Modèle de combinaison de modèles de conception (modèle composite) Prenons comme exemple la création et l'impression de la hiérarchie des employés.
17. Modèle de conception Modèle d'itérateur (Modèle d'itérateur) Prenons l'exemple de l'utilisation d'un itérateur pour imprimer les noms
18. Modèle de conception Modèle de médiateur (Modèle de médiateur) Prendre les salons de discussion publics comme exemple
19. Modèle de conception Memento Pattern (Memento Pattern) Prenons l'exemple de Memento
20. Modèle de conception Modèle d'interprète (Modèle d'interprète) Prenez l'explication d'une phrase comme exemple
21. Modèle de conception de modèle de chaîne de responsabilité (Modèle de chaîne de responsabilité) Prenons l'exemple des journaux d'impression dans Android Studio
22. Modèle de conception Modèle de visiteur (Modèle de visiteur) Prenons l'exemple de l'affichage des composants de l'ordinateur
- Observateur
- Usine
- Singleton
- Stratégie
- Adaptateur
- Commande
- Décorateur
- Façade
- Méthode de modèle
- État
- Constructeur
- Prototype
- Poids mouche
- Procuration
- Pont
- Composite
- Itérateur
- Médiateur
- Mémento
- Chaîne de responsabilité
- Visiteur
Définit des dépendances un à plusieurs entre les objets, de sorte que lorsqu'un objet change, toutes ses dépendances seront notifiées et automatiquement mises à jour.
Il existe de nombreux endroits dans JDK ou Andorid qui implémentent le modèle d'observateur, comme XXXView.addXXXListener. Bien sûr, XXXView.setOnXXXListener n'est pas nécessairement le modèle d'observateur, car le modèle d'observateur est une relation un-à-plusieurs, et pour setXXXListener, c'est une paire. La relation entre 1 et 1 devrait être appelée un rappel.
Interface spéciale : Sujet.java ;
/**
* 注册一个观察者
*/
public void registerObserver ( Observer observer );
/**
* 移除一个观察者
*/
public void removeObserver ( Observer observer );
/**
* 通知所有观察者
*/
public void notifyObservers ();
Classe d'implémentation du compte de service 3D : ObjectFor3D.java
@ Override
public void registerObserver ( Observer observer ) {
observers . add ( observer );
}
@ Override
public void removeObserver ( Observer observer ) {
int index = observers . indexOf ( observer );
if ( index >= 0 ) {
observers . remove ( index );
}
}
@ Override
public void notifyObservers () {
for ( Observer observer : observers ) {
observer . update ( msg );
}
}
/**
* 主题更新信息
*/
public void setMsg ( String msg ) {
this . msg = msg ;
notifyObservers ();
}
Tous les observateurs doivent implémenter cette interface : Observer.java
public ObserverUser1 ( Subject subject ) {
subject . registerObserver ( this );
}
@ Override
public void update ( String msg ) {
Log . e ( "-----ObserverUser1 " , "得到 3D 号码:" + msg + ", 我要记下来。" );
}
Test final : ObserverActivity.java
// 创建服务号
objectFor3D = new ObjectFor3D ();
// 创建两个订阅者
observerUser1 = new ObserverUser1 ( objectFor3D );
observerUser2 = new ObserverUser2 ( objectFor3D );
// 两个观察者,发送两条信息
objectFor3D . setMsg ( "201610121 的3D号为:127" );
objectFor3D . setMsg ( "20161022 的3D号为:000" );
Listons brièvement la famille de ce modèle :
1. Mode usine statique
2. Mode usine simple (achat de Roujiamo en magasin)
public RoujiaMo creatRoujiaMo ( String type ) {
RoujiaMo roujiaMo = null ;
switch ( type ) {
case "Suan" :
roujiaMo = new ZSuanRoujiaMo ();
break ;
case "La" :
roujiaMo = new ZLaRoujiaMo ();
break ;
case "Tian" :
roujiaMo = new ZTianRoujiaMo ();
break ;
default : // 默认为酸肉夹馍
roujiaMo = new ZSuanRoujiaMo ();
break ;
}
return roujiaMo ;
}
3. Modèle de méthode Factory (ouverture d'une succursale)
Fournit des méthodes abstraites pour créer Roujia MoStore : RoujiaMoStore.java
public abstract RoujiaMo sellRoujiaMo ( String type );
Implémentation spécifique de la méthode abstraite : XianRoujiaMoStore.java
La branche utilise toujours le modèle de fabrique simple : XianSimpleRoujiaMoFactory.java
4. Modèle d'usine abstrait (utilisant des matières premières officielles)
/**
* 准备工作
*/
public void prepare ( RoujiaMoYLFactory roujiaMoYLFactory ) {
Meet meet = roujiaMoYLFactory . creatMeet ();
YuanLiao yuanLiao = roujiaMoYLFactory . creatYuanLiao ();
Log . e ( "---RoujiaMo:" , "使用官方的原料 ---" + name + ": 揉面-剁肉-完成准备工作 yuanLiao:" + meet + "yuanLiao:" + yuanLiao );
}
Le mode singleton vise principalement à éviter le gaspillage de ressources causé par la création de plusieurs instances, et plusieurs instances peuvent facilement conduire à des résultats incorrects en raison de plusieurs appels. L'utilisation du mode singleton peut garantir qu'il n'y a qu'une seule instance dans l'ensemble de l'application .
Définition : Seules trois étapes sont nécessaires pour garantir l’unicité d’un objet
Comparez la définition :
Style Han affamé [disponible] : SingletonEHan.java
Contient le style Han paresseux [double verrouillage de vérification recommandé] : SingletonLanHan.java
private SingletonLanHan () {}
private static SingletonLanHan singletonLanHanFour ;
public static SingletonLanHan getSingletonLanHanFour () {
if ( singletonLanHanFour == null ) {
synchronized ( SingletonLanHan . class ) {
if ( singletonLanHanFour == null ) {
singletonLanHanFour = new SingletonLanHan ();
}
}
}
return singletonLanHanFour ;
}
Modèle de stratégie : définit une famille d'algorithmes et les encapsule séparément pour les rendre interchangeables. Ce modèle permet aux modifications d'algorithme d'être indépendantes des clients qui utilisent les algorithmes.
RoleA roleA = new RoleA ( "---A" );
roleA . setiDisplayBehavior ( new DisplayYZ ())
. setiAttackBehavior ( new AttackXL ())
. setiDefendBehavior ( new DefendTMS ())
. setiRunBehavior ( new RunJCTQ ());
roleA . display (); // 样子
roleA . attack (); // 攻击
roleA . run (); // 逃跑
roleA . defend (); // 防御
Définition : Convertir l'interface d'une classe en une autre interface attendue par le client. L'adaptateur permet aux classes avec des interfaces incompatibles de coopérer entre elles. Cette définition est correcte, disant que la fonction d'un adaptateur est de convertir une interface en une autre interface.
Prenons l'exemple du chargeur : les chargeurs de téléphones portables fonctionnent généralement autour de 5 V. Notre tension alternative domestique en Chine est de 220 V, le chargement des téléphones portables nécessite donc un adaptateur (réducteur de tension).
Un téléphone mobile : Mobile.java
Le téléphone s'appuie sur une interface qui fournit une tension de 5 V : V5Power.java
Ce que nous avons, c'est du courant alternatif domestique de 220 V : V220Power.java
Adaptateur pour compléter la fonction de conversion du 220V en 5V : V5PowerAdapter.java
Test final : Charger le téléphone :
Mobile mobile = new Mobile ();
V5Power v5Power = new V5PowerAdapter ( new V200Power ());
mobile . inputPower ( v5Power );
Définition : Encapsulez les « requêtes » dans des objets afin que d'autres objets puissent être paramétrés à l'aide de différentes requêtes, files d'attente ou journaux. Le mode commande prend également en charge les opérations annulables. (Simplification : encapsulez la requête dans un objet et dissociez le demandeur d'action et l'exécuteur d'action.)
QuickCommand quickCloseCommand = new QuickCommand ( new Command []{ new LightOffCommand ( light ), new ComputerOffCommand ( computer ), new DoorCloseCommand ( door )});
controlPanel . setCommands ( 6 , quickOpenCommand );
controlPanel . keyPressed ( 6 );
controlPanel . setCommands ( 0 , new DoorOpenCommand ( door )); // 开门
controlPanel . keyPressed ( 0 );
Modèle de décorateur : pour étendre les fonctionnalités, les décorateurs offrent une alternative plus flexible à l’intégration, en attachant dynamiquement des responsabilités aux objets.
Décrivons brièvement où le modèle décorateur entre en jeu. Lorsque nous concevons une classe, nous devons ajouter des fonctions auxiliaires à cette classe, et nous ne voulons pas changer le code de cette classe. jouer. Il est temps. Cela reflète également un principe : les classes doivent être ouvertes aux extensions et fermées aux modifications.
Exigences : Concevoir le système d'équipement du jeu. L'exigence de base est de pouvoir calculer la puissance d'attaque et la description de chaque équipement après avoir été intégré à diverses gemmes :
1. Super classe d'équipement : IEquip.java
2. Classes de mise en œuvre de chaque équipement :
3. Super classe de décorations (les décorations appartiennent également aux équipements) : IEquipDecorator.java
4. Classe de mise en œuvre des décorations :
5. Test final : calculez la puissance d'attaque et affichez la description :
Log . e ( "---" , "一个镶嵌2颗红宝石,1颗蓝宝石的靴子: " );
IEquip iEquip = new RedGemDecorator ( new RedGemDecorator ( new BlueGemDecorator ( new ShoeEquip ())));
Log . e ( "---" , "攻击力:" + iEquip . caculateAttack ());
Log . e ( "---" , "描述语:" + iEquip . description ());
Définition : fournir une interface unifiée pour accéder à un groupe d'interfaces dans le sous-système. L'apparence définit une interface de haut niveau pour faciliter l'utilisation du sous-système. En fait, pour la commodité des clients, un groupe d’opérations est encapsulé dans une méthode.
Demande : je préfère regarder des films, j'ai donc acheté un projecteur, un ordinateur, une chaîne stéréo, conçu l'éclairage de la pièce et acheté une machine à pop-corn. Ensuite, lorsque je veux regarder un film, j'ai besoin d'une visualisation et d'un arrêt en un clic. .
Commutation et autres opérations pour chaque classe d'appareil :
par exemple : Machine à pop-corn : PopcornPopper.java
Cours de cinéma : HomeTheaterFacade.java
/**
* 一键观影
*/
public void watchMovie () {
computer . on ();
light . down ();
popcornPopper . on ();
popcornPopper . makePopcorn ();
projector . on ();
projector . open ();
player . on ();
player . make3DListener ();
}
Test final : visionnage de films en un clic :
new HomeTheaterFacade ( computer , light , player , popcornPopper , projector ). watchMovie ();
Définition : définit le squelette d'un algorithme et reporte certaines étapes aux sous-classes. La méthode modèle permet aux sous-classes de redéfinir les étapes de l'algorithme sans modifier la structure de l'algorithme.
Exigences : Décrivez brièvement : Notre société dispose de programmeurs, de testeurs, de RH, de chefs de projet, etc. Le mode méthode modèle est utilisé ci-dessous pour enregistrer l'état de travail de tout le personnel.
Trois types de rôles dans le modèle de méthode modèle
1. Méthode concrète
2. Méthode abstraite
3. Méthode du crochet
Superclasse de travailleurs : Worker.java
// 具体方法
public final void workOneDay () {
Log . e ( "workOneDay" , "-----------------work start----------------" );
enterCompany ();
work ();
exitCompany ();
Log . e ( "workOneDay" , "-----------------work end----------------" );
}
// 工作 抽象方法
public abstract void work ();
// 钩子方法
public boolean isNeedPrintDate () {
return false ;
}
private void exitCompany () {
if ( isNeedPrintDate ()) {
Log . e ( "exitCompany" , "---" + new Date (). toLocaleString () + "--->" );
}
Log . e ( "exitCompany" , name + "---离开公司" );
}
Classe d'implémentation du programmeur (l'heure peut être connue) : ITWorker.java
/**
* 重写父类的此方法,使可以查看离开公司时间
*/
@ Override
public boolean isNeedPrintDate () {
return true ;
}
Essai final :
Voyez comment tout le monde travaille :
QAWorker qaWorker = new QAWorker ( "测试人员" );
qaWorker ();
HRWorker hrWorker = new HRWorker ( "莉莉姐" );
hrWorker . workOneDay ();
...
Vérifiez quand le programmeur a quitté l'entreprise :
ITWorker itWorker = new ITWorker ( "jingbin" );
itWorker . workOneDay ();
Définition : Permet à un objet de changer de comportement lorsque son état interne change, faisant apparaître l'objet comme s'il avait modifié sa classe.
La définition recommence à être floue. Pensez-y. Lorsque l'état interne d'un objet change, son comportement change avec le changement d'état.
Exigences : Prenons l'exemple d'un distributeur automatique (il existe des statuts tels que pièce insérée et non insérée, ainsi que des méthodes d'insertion et de retour de pièces)
Implémentation initiale du distributeur automatique à améliorer : VendingMachine.java
Distributeur automatique amélioré (plus malléable) : VendingMachineBetter.java
// 放钱
public void insertMoney () {
currentState . insertMoney ();
}
// 退钱
public void backMoney () {
currentState . backMoney ();
}
// 转动曲柄
public void turnCrank () {
currentState . turnCrank ();
if ( currentState == soldState || currentState == winnerState ) {
currentState . dispense (); //两种情况会出货
}
}
// 出商品
public void dispense () {
Log . e ( "VendingMachineBetter" , "---发出一件商品" );
if ( count > 0 ) {
count --;
}
}
// 设置对应状态
public void setState ( State state ) {
this . currentState = state ;
}
Interface d'état : State.java
Classe d'implémentation d'interface correspondant à l'état :
Test de distributeur automatique amélioré :
// 初始化售货机,且里面有3个商品
VendingMachineBetter machineBetter = new VendingMachineBetter ( 3 );
machineBetter . insertMoney ();
machineBetter . turnCrank ();
Le mode construction est le mode de création d'objet. Le mode construction peut séparer la représentation interne d'un produit du processus de production du produit, de sorte qu'un processus de construction puisse générer des objets produit avec différentes représentations internes.
Conditions requises : les utilisateurs se rendent dans un magasin automobile pour acheter une voiture.
Analyse : Le garage automobile extrait les voitures correspondantes en fonction des besoins de chaque utilisateur
Superclasse de constructeur : Builder
public abstract class Builder {
public abstract void setPart ( String name , String type );
public abstract Product getProduct ();
}
Classe d'implémentation correspondante du constructeur : ConcreteBuilder
public class ConcreteBuilder extends Builder {
private Product product = new Product ();
@ Override
public void setPart ( String name , String type ) {
product . setName ( name );
product . setType ( type );
}
@ Override
public Product getProduct () {
return product ;
}
}
Le gérant du magasin récupère la voiture :
// 店长
Director director = new Director ();
// 得到宝马汽车,内部实现提取宝马汽车的详情操作
Product product = director . getBProduct ();
// 展示汽车信息
product . showProduct ();
Le modèle de prototype est utilisé pour créer des objets répétés tout en garantissant les performances. Ce type de modèle de conception est un modèle de création qui offre une manière optimale de créer des objets.
Ce modèle implémente une interface prototype utilisée pour créer un clone de l'objet actuel. Ce mode est utilisé lorsque le coût de création directe d'objets est relativement élevé. Par exemple, un objet doit être créé après une opération de base de données coûteuse. Nous pouvons mettre l'objet en cache, en renvoyer un clone lors de la prochaine requête et mettre à jour la base de données si nécessaire pour réduire les appels à la base de données.
En prenant comme exemple l’obtention de plusieurs formes, il y a quatre étapes :
1. Créez une classe abstraite qui implémente l'interface Cloneable. Forme (implémente clonable)
public abstract class Shape implements Cloneable {
private String id ;
protected String type ;
public abstract void draw ();
public String getId () {
return id ;
}
public void setId ( String id ) {
this . id = id ;
}
@ Override
public Object clone () {
Object object = null ;
try {
object = super . clone ();
} catch ( CloneNotSupportedException e ) {
Log . e ( "--" , e . getMessage ());
}
return object ;
}
}
2. Créez une classe d'entité qui étend la classe abstraite ci-dessus. Cercle, Rectangle, Carré
public class Circle extends Shape {
public Circle () {
type = "Circle" ;
}
@ Override
public void draw () {
Log . e ( "---" , "Inside Circle::draw() method." );
}
}
3. Créez une classe pour obtenir les classes d'entités de la base de données et stockez-les dans une table de hachage. Cache de forme
public class ShapeCache {
private static Hashtable < String , Shape > shapeMap = new Hashtable < String , Shape >();
public static Shape getShape ( String shapeId ) {
Shape shapeCache = shapeMap . get ( shapeId );
return ( Shape ) shapeCache . clone ();
}
// 对每种形状都运行数据库查询,并创建该形状
// shapeMap.put(shapeKey, shape);
// 例如,我们要添加三种形状
public static void loadCache () {
Circle circle = new Circle ();
circle . setId ( "1" );
shapeMap . put ( circle . getId (), circle );
Rectangle rectangle = new Rectangle ();
rectangle . setId ( "2" );
shapeMap . put ( rectangle . getId (), rectangle );
Square square = new Square ();
square . setId ( "3" );
shapeMap . put ( square . getId (), square );
}
}
4. Utilisez la classe ShapeCache pour obtenir un clone de la forme stockée dans la table de hachage.
// 使用 ShapeCache 类来获取存储在 Hashtable 中的形状的克隆。
ShapeCache . loadCache ();
Shape shapeCache1 = ShapeCache . getShape ( "1" );
Shape shapeCache2 = ShapeCache . getShape ( "2" );
Shape shapeCache3 = ShapeCache . getShape ( "3" );
Principalement utilisé pour réduire le nombre d'objets créés afin de réduire l'utilisation de la mémoire et d'améliorer les performances. Ce type de modèle de conception est un modèle structurel qui permet de réduire le nombre d'objets et ainsi d'améliorer la structure des objets requise par l'application.
Le modèle Flyweight tente de réutiliser des objets existants du même type ou de créer de nouveaux objets si aucun objet correspondant n'est trouvé. Nous allons démontrer ce modèle en créant 5 objets qui dessinent 20 cercles à différents endroits. Puisqu'il n'y a que 5 couleurs disponibles, la propriété color est utilisée pour vérifier l'objet Circle existant.
En prenant comme exemple l’obtention aléatoire de plusieurs formes, il y a quatre étapes :
1. Créez une interface.
public interface Shape {
void draw ();
}
2. Créez une classe d'entité qui implémente l'interface.
public class Circle implements Shape {
private String color ;
private int x ;
private int y ;
private int radius ;
public Circle ( String color ) {
this . color = color ;
}
public void setX ( int x ) {
this . x = x ;
}
public void setY ( int y ) {
this . y = y ;
}
public void setRadius ( int radius ) {
this . radius = radius ;
}
@ Override
public void draw () {
Log . e ( "---" , "Circle: Draw() [Color : " + color
+ ", x : " + x + ", y :" + y + ", radius :" + radius );
}
}
3. Créez une usine pour générer des objets de classes d'entités en fonction des informations données.
public class ShapeFactory {
private static final HashMap < String , Shape > circleMap = new HashMap < String , Shape >();
public static Shape getShape ( String color ) {
Shape shape = circleMap . get ( color );
if ( shape == null ) {
shape = new Circle ( color );
circleMap . put ( color , shape );
Log . e ( "getShape" , "Creating circle of color : " + color );
}
return shape ;
}
}
4. Utilisez cette fabrique pour obtenir l'objet de la classe d'entité en transmettant des informations de couleur.
for ( int i = 0 ; i < 20 ; i ++) {
Circle circle = ( Circle ) ShapeFactory . getShape ( getRandomColor ());
circle . setX ( getRandomX ());
circle . setY ( getRandomY ());
circle . setRadius ( 100 );
circle . draw ();
}
Une classe représente la fonctionnalité d'une autre classe. Dans le modèle proxy, nous créons des objets avec des objets existants afin de fournir une interface fonctionnelle avec le monde extérieur. On peut comprendre que s'il n'y a pas un tel objet dans la mémoire, il sera créé, et s'il y en a, l'objet sera renvoyé directement.
En prenant l'exemple de l'obtention d'images à partir d'un disque, il y a trois étapes au total :
1. Créez une interface.
public interface Image {
void display ();
}
2. Créez une classe d'entité RealImage qui implémente l'interface. Classe proxy correspondante : ProxyImage.
public class RealImage implements Image {
private String fileName ;
public RealImage ( String fileName ) {
this . fileName = fileName ;
loadFromDisk ( fileName );
}
private void loadFromDisk ( String fileName ) {
Log . e ( "RealImage" , "loading " + fileName );
}
@ Override
public void display () {
Log . e ( "RealImage" , "Displaying " + fileName );
}
}
public class ProxyImage implements Image {
private String fileName ;
private RealImage realImage ;
public ProxyImage ( String fileName ) {
this . fileName = fileName ;
}
@ Override
public void display () {
if ( realImage == null ) {
realImage = new RealImage ( fileName );
}
realImage . display ();
}
}
3. Lorsque cela vous est demandé, utilisez ProxyImage pour obtenir un objet de la classe RealImage.
Image image = new ProxyImage ( "test_10mb.png" );
// 第一次是new的,图像从磁盘加载
image . display ();
// 第二次取缓存,图像不需要从磁盘加载
image . display ();
Bridge est utilisé pour découpler l'abstraction et l'implémentation afin que les deux puissent changer indépendamment. Ce type de modèle de conception est un modèle structurel qui dissocie l'abstraction et la mise en œuvre en fournissant une structure de pont entre elles.
En prenant comme exemple de dessiner des cercles de différentes couleurs, la mise en œuvre est divisée en cinq étapes :
1. Créez une interface d'implémentation de pont.
public interface DrawAPI {
void drawCircle ( int radius , int x , int y );
}
2. Créez une classe d'implémentation de pont d'entité qui implémente l'interface DrawAPI. Cercle Rouge, Cercle Vert
public class RedCircle implements DrawAPI {
@ Override
public void drawCircle ( int radius , int x , int y ) {
Log . e ( "---" , "Drawing Circle[ color: red, radius: "
+ radius + ", x: " + x + ", " + y + "]" );
}
}
3. Utilisez l'interface DrawAPI pour créer la classe abstraite Shape.
public abstract class Shape {
protected DrawAPI drawAPI ;
protected Shape ( DrawAPI drawAPI ) {
this . drawAPI = drawAPI ;
}
public abstract void draw ();
}
4. Créez une classe d'entité qui implémente l'interface Shape.
public class Circle extends Shape {
private int x , y , radius ;
protected Circle ( int x , int y , int radius , DrawAPI drawAPI ) {
super ( drawAPI );
this . x = x ;
this . y = y ;
this . radius = radius ;
}
@ Override
public void draw () {
drawAPI . drawCircle ( radius , x , y );
}
}
5. Utilisez les classes Shape et DrawAPI pour dessiner des cercles de différentes couleurs.
// 画红圆
Circle circle = new Circle ( 10 , 10 , 100 , new RedCircle ()); s
circle . draw ();
// 画绿圆
Circle circle2 = new Circle ( 20 , 20 , 100 , new GreenCircle ());
circle2 . draw ();
Également appelé modèle partie-tout, il est utilisé pour traiter un groupe d’objets similaires comme un objet unique. Le mode composition combine les objets selon une structure arborescente, qui est utilisée pour représenter des hiérarchies partielles et entières. Ce type de modèle de conception est un modèle structurel, qui crée une structure arborescente de groupes d’objets.
Prenons comme exemple la création et l'impression d'une hiérarchie d'employés, l'exemple de la plus petite unité :
1. Créez une classe Employee avec une liste d’objets Employee.
public class Employee {
private String name ;
// 部门
private String dept ;
// 工资
private int salary ;
// 员工 list
private List < Employee > subordinates ;
public Employee ( String name , String dept , int salary ) {
this . name = name ;
this . dept = dept ;
this . salary = salary ;
this . subordinates = new ArrayList < Employee >();
}
public void add ( Employee e ) {
subordinates . add ( e );
}
public void remove ( Employee e ) {
subordinates . remove ( e );
}
public List < Employee > getSubordinates () {
return subordinates ;
}
@ Override
public String toString () {
return "Employee{" +
"name='" + name + ''' +
", dept='" + dept + ''' +
", salary=" + salary +
", subordinates=" + subordinates +
'}' ;
}
}
2. Utilisez la classe Employee pour créer et imprimer la hiérarchie des employés.
final Employee ceo = new Employee ( "John" , "CEO" , 30000 );
Employee headSales = new Employee ( "Robert" , "Head sales" , 20000 );
Employee headMarketing = new Employee ( "Michel" , "Head Marketing" , 20000 );
Employee clerk1 = new Employee ( "Laura" , "Marketing" , 10000 );
Employee clerk2 = new Employee ( "Bob" , "Marketing" , 10000 );
Employee salesExecutive1 = new Employee ( "Richard" , "Sales" , 10000 );
Employee salesExecutive2 = new Employee ( "Rob" , "Sales" , 10000 );
ceo . add ( headSales );
ceo . add ( headMarketing );
headSales . add ( salesExecutive1 );
headSales . add ( salesExecutive2 );
headMarketing . add ( clerk1 );
headMarketing . add ( clerk2 );
Log . e ( "---" , ceo . toString ());
// 打印
/*
* Employee{name='John', dept='CEO', salary=30000,
* subordinates=[Employee{name='Robert', dept='Head sales', salary=20000,
* subordinates=[
* Employee{name='Richard', dept='Sales', salary=10000, subordinates=[]},
* Employee{name='Rob', dept='Sales', salary=10000, subordinates=[]}]},
* Employee{name='Michel', dept='Head Marketing', salary=20000,
* subordinates=[Employee{name='Laura', dept='Marketing', salary=10000, subordinates=[]},
* Employee{name='Bob', dept='Marketing', salary=10000, subordinates=[]}]}]}
*/
Modèle de conception très courant dans les environnements de programmation Java et .Net. Ce modèle est utilisé pour accéder séquentiellement aux éléments d'un objet de collection sans connaître la représentation sous-jacente de l'objet de collection. Le modèle itérateur est un modèle comportemental.
En prenant l'exemple de l'utilisation d'un itérateur pour imprimer les noms, il y a trois étapes au total :
1. Créez une interface :
public interface Iterator {
public boolean hasNext ();
public Object next ();
}
public interface Container {
public Iterator getIterator ();
}
2. Créez une classe d'entité qui implémente l'interface Container. Cette classe possède une classe interne NameIterator qui implémente l'interface Iterator.
public class NameRepository implements Container {
private String names [] = { "John" , "jingbin" , "youlookwhat" , "lookthis" };
@ Override
public Iterator getIterator () {
return new NameIterator ();
}
private class NameIterator implements Iterator {
int index ;
@ Override
public boolean hasNext () {
if ( index < names . length ) {
return true ;
}
return false ;
}
@ Override
public Object next () {
if ( hasNext ()) {
return names [ index ++];
}
return null ;
}
}
}
3. Utilisez NameRepository pour obtenir l'itérateur et imprimer le nom.
NameRepository nameRepository = new NameRepository ();
for ( Iterator iterator = nameRepository . getIterator (); iterator . hasNext (); ) {
String name = ( String ) iterator . next ();
Log . e ( "---" , name );
/*
* /---: John
* /---: jingbin
* /---: youlookwhat
* /---: lookthis
*/
}
Utilisé pour réduire la complexité de la communication entre plusieurs objets et classes. Ce modèle fournit une classe intermédiaire qui gère généralement la communication entre différentes classes et prend en charge le couplage lâche, ce qui rend le code plus facile à maintenir. Le modèle médiateur est un modèle comportemental.
En prenant un salon de discussion public comme exemple, les étapes minimales d'un exemple d'unité sont :
1. Créez une classe intermédiaire.
public class CharRoom {
public static void showMessage ( User user , String message ) {
Log . e ( "---" , new Date (). toString ()
+ " [" + user . getName () + "] : " + message );
}
}
2. Créez la classe d'utilisateurs.
public class User {
private String name ;
public User ( String name ) {
this . name = name ;
}
public String getName () {
return name ;
}
public void setName ( String name ) {
this . name = name ;
}
public void sendMessage ( String message ) {
// 使用中介类
CharRoom . showMessage ( this , message );
}
}
3. Utilisez l'objet Utilisateur pour afficher la communication entre eux.
User jingbin = new User ( "jingbin" );
jingbin . sendMessage ( "Hi~ youlookwhat!" );
//---: Sun Feb 02 08:11:47 GMT+00:00 2020 [jingbin] : Hi~ youlookwhat!
User jingbin = new User ( "youlookwhat" );
jingbin . sendMessage ( "Hi~ jingbin!" );
//---: Sun Feb 02 08:11:49 GMT+00:00 2020 [youlookwhat] : Hi~ jingbin!
Enregistrez un certain état d'un objet afin qu'il puisse être restauré à un moment approprié. Le mode mémo est un mode comportemental.
En prenant le mémo comme exemple, les étapes unitaires minimales sont :
1. Créez la classe Memento.
public class Memento {
private String state ;
public Memento ( String state ) {
this . state = state ;
}
public String getState () {
return state ;
}
public void setState ( String state ) {
this . state = state ;
}
}
2. Créez la classe Originator.
public class Originator {
private String state ;
public String getState () {
return state ;
}
public void setState ( String state ) {
this . state = state ;
}
public Memento setSateToMemento () {
return new Memento ( state );
}
public String getStateFromMemento ( Memento memento ) {
return memento . getState ();
}
}
3. Créez la classe CareTaker.
public class CareTaker {
private List < Memento > mementoList = new ArrayList < Memento >();
public void add ( Memento memento ) {
mementoList . add ( memento );
}
public Memento get ( int index ) {
return mementoList . get ( index );
}
}
4. Utilisez les objets CareTaker et Originator.
// 管理者
CareTaker careTaker = new CareTaker ();
Originator originator = new Originator ();
originator . setState ( "State #1" );
originator . setState ( "State #2" );
// 保存状态
careTaker . add ( originator . setSateToMemento ());
originator . setState ( "State #3" );
// 保存状态
careTaker . add ( originator . setSateToMemento ());
originator . setState ( "State #4" );
Log . e ( "---" , "Current State: " + originator . getState ());
// 得到保存的状态
String fromMemento1 = originator . getStateFromMemento ( careTaker . get ( 0 ));
Log . e ( "---" , "First Saved State: " + fromMemento1 );
String fromMemento2 = originator . getStateFromMemento ( careTaker . get ( 1 ));
Log . e ( "---" , "Second Saved State: " + fromMemento2 );
/*
* /---: Current State: State #4
* /---: First Saved State: State #2
* /---: Second Saved State: State #3
*/
Fournit un moyen d’évaluer la grammaire ou les expressions d’une langue et constitue un modèle de comportement. Ce modèle implémente une interface d'expression qui interprète un contexte spécifique. Ce mode est utilisé dans l'analyse SQL, les moteurs de traitement de symboles, etc.
Prenons l'exemple de l'explication d'une phrase, les étapes unitaires minimales :
1. Créez une interface d'expression Expression.
public interface Expression {
public boolean interpreter ( String content );
}
2. Créez une classe d'entité qui implémente l'interface ci-dessus. TerminalExpression, OuExpression et AndExpression.
public class TerminalExpression implements Expression {
private String data ;
public TerminalExpression ( String data ) {
this . data = data ;
}
@ Override
public boolean interpreter ( String content ) {
// 是包含判断
return content . contains ( data );
}
}
public class OrExpression implements Expression {
private Expression expression1 ;
private Expression expression2 ;
public OrExpression ( Expression expression1 , Expression expression2 ) {
this . expression1 = expression1 ;
this . expression2 = expression2 ;
}
@ Override
public boolean interpreter ( String content ) {
return expression1 . interpreter ( content ) || expression2 . interpreter ( content );
}
}
public class AndExpression implements Expression {
private Expression expression1 ;
private Expression expression2 ;
public AndExpression ( Expression expression1 , Expression expression2 ) {
this . expression1 = expression1 ;
this . expression2 = expression2 ;
}
@ Override
public boolean interpreter ( String content ) {
return expression1 . interpreter ( content ) && expression2 . interpreter ( content );
}
}
3. Utilisez la classe Expression pour créer des règles et les analyser.
/**
* 规则:jingbin 和 youlookwhat 是男性
*/
public static Expression getMaleExpression () {
TerminalExpression jingbin = new TerminalExpression ( "jingbin" );
TerminalExpression youlookwhat = new TerminalExpression ( "youlookwhat" );
return new OrExpression ( jingbin , youlookwhat );
}
/**
* 规则:Julie 是一个已婚的女性
*/
public static Expression getMarriedWomanExpression () {
TerminalExpression julie = new TerminalExpression ( "Julie" );
TerminalExpression married = new TerminalExpression ( "Married" );
return new AndExpression ( julie , married );
}
Expression maleExpression = getMaleExpression ();
// jingbin is male: true
Log . e ( "---" , "jingbin is male: " + maleExpression . interpreter ( "jingbin" ));
Expression womanExpression = getMarriedWomanExpression ();
// Julie is married woman: true
Log . e ( "---" , "Julie is married woman: " + womanExpression . interpreter ( "Married Julie" ));
Le modèle de chaîne de responsabilité crée une chaîne d’objets destinataires pour une demande. Ce modèle découple l'expéditeur et le destinataire de la demande en fonction du type de demande. Ce type de modèle de conception est un modèle comportemental. Dans ce modèle, chaque récepteur contient généralement une référence à un autre récepteur. Si un objet ne peut pas gérer la requête, il transmet la même requête au destinataire suivant, et ainsi de suite.
En prenant comme exemple les journaux d'impression dans Android Studio, les étapes unitaires minimales sont :
1. Créez une classe de journalisation abstraite AbstractLogger.
public abstract class AbstractLogger {
public static int INFO = 1 ;
public static int DEBUG = 2 ;
public static int ERROR = 3 ;
protected int level ;
// 责任链中的下一个元素
protected AbstractLogger nextLogger ;
public void setNextLogger ( AbstractLogger nextLogger ) {
this . nextLogger = nextLogger ;
}
public void logMessage ( int level , String message ) {
if ( this . level <= level ) {
write ( message );
}
// 递归效果,不断调用下一级 logMessage
if ( nextLogger != null ) {
nextLogger . logMessage ( level , message );
}
}
protected abstract void write ( String message );
}
2. Créez une classe d'entité qui étend la classe de journalisation.
public class ConsoleLogger extends AbstractLogger {
public ConsoleLogger ( int level ) {
this . level = level ;
}
@ Override
protected void write ( String message ) {
Log . e ( "---" , "Standard Console::Logger " + message );
}
}
public class FileLogger extends AbstractLogger {
public FileLogger ( int level ) {
this . level = level ;
}
@ Override
protected void write ( String message ) {
Log . e ( "---" , "File::Logger " + message );
}
}
public class ErrorLogger extends AbstractLogger {
public ErrorLogger ( int level ) {
this . level = level ;
}
@ Override
protected void write ( String message ) {
Log . e ( "---" , "Error Console::Logger " + message );
}
}
3. Créez différents types d'enregistreurs. Donnez-leur différents niveaux d'erreur et dans chaque enregistreur, définissez l'enregistreur suivant. L'enregistreur suivant dans chaque enregistreur représente une partie de la chaîne.
public static AbstractLogger getChainOfLoggers () {
ErrorLogger errorLogger = new ErrorLogger ( AbstractLogger . ERROR );
FileLogger fileLogger = new FileLogger ( AbstractLogger . DEBUG );
ConsoleLogger consoleLogger = new ConsoleLogger ( AbstractLogger . INFO );
errorLogger . setNextLogger ( fileLogger );
fileLogger . setNextLogger ( consoleLogger );
return errorLogger ;
}
AbstractLogger logger = getChainOfLoggers ();
// ---: Standard Console::Logger this is an information.
logger . logMessage ( AbstractLogger . INFO , "this is an information." );
// ---: File::Logger this is a debug level information.
// ---: Standard Console::Logger this is a debug level information.
logger . logMessage ( AbstractLogger . DEBUG , "this is a debug level information." );
// ---: Error Console::Logger this is a error level information.
// ---: File::Logger this is a error level information.
// ---: Standard Console::Logger this is a error level information.
logger . logMessage ( AbstractLogger . ERROR , "this is a error level information." );
Dans le modèle visiteur, nous utilisons une classe visiteur, qui modifie l'algorithme d'exécution de la classe d'élément. De cette manière, l'algorithme d'exécution de l'élément peut changer au fur et à mesure que le visiteur change. Ce type de modèle de conception est un modèle comportemental. Selon le schéma, l'objet élément a accepté un objet visiteur afin que l'objet visiteur puisse gérer les opérations sur l'objet élément.
En prenant comme exemple les composants d'un ordinateur d'affichage, il est principalement mis en œuvre en cinq étapes :
1. Définissez une interface qui représente l'élément.
public interface ComputerPart {
public void accept ( ComputerPartVisitor computerPartVisitor );
}
2. Créez une classe d'entité qui étend la classe ci-dessus. Clavier, moniteur, souris, ordinateur
public class Computer implements ComputerPart {
private ComputerPart [] parts ;
public Computer () {
this . parts = new ComputerPart []{ new Mouse (), new Keyboard (), new Monitor ()};
}
@ Override
public void accept ( ComputerPartVisitor computerPartVisitor ) {
for ( ComputerPart part : parts ) {
part . accept ( computerPartVisitor );
}
computerPartVisitor . visit ( this );
}
}
public class Mouse implements ComputerPart {
@ Override
public void accept ( ComputerPartVisitor computerPartVisitor ) {
computerPartVisitor . visit ( this );
}
}
3. Définissez une interface qui représente les visiteurs.
public interface ComputerPartVisitor {
public void visit ( Computer computer );
public void visit ( Mouse mouse );
public void visit ( Keyboard keyboard );
public void visit ( Monitor monitor );
}
4. Créez des visiteurs d'entité qui implémentent les classes ci-dessus.
public class ComputerPartDisplayVisitor implements ComputerPartVisitor {
@ Override
public void visit ( Computer computer ) {
Log . e ( "---" , "Displaying Computer." );
}
@ Override
public void visit ( Mouse mouse ) {
Log . e ( "---" , "Displaying Mouse." );
}
@ Override
public void visit ( Keyboard keyboard ) {
Log . e ( "---" , "Displaying Keyboard." );
}
@ Override
public void visit ( Monitor monitor ) {
Log . e ( "---" , "Displaying Monitor." );
}
}
5. Utilisez ComputerPartDisplayVisitor pour afficher les composants de l'ordinateur.
ComputerPart computer = new Computer ();
computer . accept ( new ComputerPartDisplayVisitor ());
/*
*打印:
*---: Displaying Mouse.
*---: Displaying Keyboard.
*---: Displaying Monitor.
*---: Displaying Computer.
*/