Notes sur les modèles de conception Java pour les débutants – Modèle de prototype

Le mode prototype est également appelé mode modèle original.

 

1. Objectif :
utiliser des instances de prototypes pour spécifier les types d'objets à créer et créer de nouveaux objets en copiant ces prototypes.

 

2. Participants :
•Prototype abstrait (Prototype) : déclare une interface qui se clone.
•Concrete Prototype : met en œuvre une opération de clonage lui-même.
• Client : laissez un prototype se cloner pour créer un nouvel objet.

 

3. Structure :



 

 

Par définition, le modèle prototype est utilisé pour copier des objets.

 

Alors, quand utiliser le mode prototype ?

 

Prenons l’exemple de la production automobile pour comprendre. 

Tout d'abord, selon la définition, le mode prototype doit se cloner , cela signifie donc qu'il doit y avoir un prototype de produit.

En d'autres termes, le prototype dans le modèle de prototype doit toujours être créé d'abord via la méthode d'usine ou d'autres méthodes.

 

De ce point de vue, le modèle prototype est utilisé lors de la production de plusieurs objets produits identiques ou similaires.

 

Alors, quels sont les avantages d’utiliser un modèle prototype ?

 

Dans l’hypothèse qu’une Audi A6 soit produite, pensez à utiliser le mode usine (voire le mode constructeur).

 

1. Si je possède une Audi A6, ce qui est très bien, et que mon ami en veut une aussi, mais nous ne savons pas dans quelle usine elle est produite et nous ne savons pas où l'acheter. Si je pouvais faire une copie de mon Audi A6, ce serait très pratique pour mes amis, et ils n’auraient même pas à dépenser d’argent. (C'est un doux rêve !!)

En utilisant le mode prototype, clonez-le simplement.

De cette façon, il n'est pas nécessaire de savoir dans quelle usine le produit est fabriqué, il suffit de le copier et vous pouvez rapidement obtenir un nouvel objet produit.

Cela rend le système plus indépendant de la création, de la composition et de la présentation du produit . Parce qu'il est créé par lui-même pour réaliser le produit lui-même.

 

2. Si vous devez reproduire d'autres modèles de voitures, comme l'Audi A8.

En mode usine, nous devons généralement construire une autre usine Audi A8.

 

Étant donné que l'Audi A8 et l'Audi A6 sont du même niveau de produit, si vous clonez un objet produit Audi A6 et modifiez certains attributs, vous pouvez créer un nouvel objet produit Audi A8. De cette façon, aucune nouvelle usine n’est nécessaire. (Les constructeurs rêvent aussi !!)

Autrement dit, cela évite de créer une hiérarchie de classes d’usine parallèle à la hiérarchie de classes de produits.

 

 

 Grâce à l'utilisation du mode prototype, le processus de création de produit est plus indépendant et ne nécessite pas de classe d'usine correspondante. Il est créé à l'aide de méthodes au sein du produit. Par conséquent, il est plus facile d’ajouter dynamiquement de nouvelles catégories de produits et de réduire les catégories de produits d’origine sans affecter la structure du système d’origine.

 

 

Comment implémenter le mode prototype ?

Il s'agit de réaliser l'auto-réplication (clonage) du prototype. Cela implique les concepts de clonage superficiel et de clonage profond : (Extrait de "Java and Patterns" de Yan Hong)

1. Copie superficielle (clone superficiel)
Toutes les variables de l'objet copié contiennent les mêmes valeurs que l'objet d'origine, et toutes les références à d'autres objets pointent toujours vers l'objet d'origine. En d’autres termes, une copie superficielle ne copie que l’objet en question, pas les objets auxquels il fait référence.

2. Copie profonde (clonage profond)
toutes les variables de l'objet copié contiennent les mêmes valeurs que l'objet d'origine, à l'exception des variables qui font référence à d'autres objets. Les variables qui font référence à d'autres objets pointeront vers les nouveaux objets copiés, plutôt que vers les objets référencés d'origine. En d’autres termes, la copie profonde copie tous les objets référencés par l’objet à copier.

 

3. Le processus d'utilisation de la sérialisation pour effectuer une copie approfondie
et écrire l'objet dans le flux est le processus de sérialisation, mais dans le cercle des programmeurs Java, il est également appelé de manière très vivante le processus de « gel » ou de « décapage ». ; La parallélisation ( Le processus de désérialisation) de lecture des objets du flux est appelé processus de « décongélation » ou de « dépicking ». Il convient de souligner que ce qui est écrit dans le flux est une copie de l'objet, et que l'objet original existe toujours dans la JVM. Par conséquent, ce qui est « picklé en cornichons » n'est qu'une copie de l'objet, et les cornichons Java peuvent être encore frais.
Pour copier en profondeur un objet dans le langage Java, vous pouvez souvent d'abord faire en sorte que l'objet implémente l'interface Serialisable, puis écrire l'objet (en fait juste une copie de l'objet) dans un flux (le transformer en cornichon), puis le lire. sorti du ruisseau (remettre le cornichon dans le ruisseau). frais), l'objet peut être reconstruit.

 

Méthode clone() de Java :
la méthode clone copie une copie de l'objet et la renvoie à l'appelant. De manière générale, la méthode clone() satisfait :
① Pour tout objet x, il existe x.clone() !=x//L'objet cloné n'est pas le même objet que l'objet d'origine
② Pour tout objet x, il existe x. clone ().getClass()= =x.getClass()//L'objet cloné a le même type que l'objet d'origine
③ Si la méthode equals() de l'objet x est correctement définie, alors x.clone().equals( x) devrait être vrai.

Clonage d'objets en Java
① Afin d'obtenir une copie de l'objet, on peut utiliser la méthode clone() de la classe Object.
② Remplacez la méthode clone() de la classe de base dans la classe dérivée et déclarez-la comme publique.
③Dans la méthode clone() de la classe dérivée, appelez super.clone().
④Implémentez l'interface Cloneable dans la classe dérivée.

 

Code implémenté en Java :

Copie superficielle (clone superficiel) :

Catégorie automobile :

 

/*
 * 汽车类
 * 
 * 浅克隆(shadow clone)的实现
 */
public class Car implements Cloneable {
	
//	汽车款式
	public int type;

//	引用的其他对象,汽车发动机
	public Engine engine;

	public Object clone() {
		
		Object clone = null;
		try {

//			这里只是克隆的自己本身
			clone = super.clone();
			
//			为什么在派生类中覆盖Object的clone()方法时,一定要调用super.clone()呢?
//			因为,在运行时刻,Object中的clone()识别出你要复制的是哪一个对象,然后为此对象分配空间,并进行对象的复制,
//			将原始对象的内容一一复制到新对象的存储空间中。	
			
		} catch (CloneNotSupportedException e) {

		}
		return clone;
	}

}

 

Type de moteur:

/*
 * 汽车发动机类,汽车类中引用的对象的类
 */
public class Engine implements Cloneable {
	
//	汽车发动机型号
	public int model;

}

 

Appel client :

/*
 * 浅克隆(shadow clone)的调用
 */
public class Client {
	   public static  void main(String argv[])
	   {
		 System.out.println("-----创建汽车1-----");
		 Car car1=new Car();
	     car1.engine=new Engine();
	     car1.type=1;
	     car1.engine.model=1;
	     System.out.println("汽车1款式:"+car1.type+"\t汽车1的发动机型号:"+car1.engine.model);
	     
	     System.out.println("----汽车1--克隆-->汽车2----");
	     Car car2=(Car)car1.clone();
	     car2.type=2;
	     car2.engine.model=2;
	     
	     System.out.println("汽车2款式:"+car2.type+"\t汽车2的发动机型号:"+car2.engine.model);
	     System.out.println("汽车1款式:"+car1.type+"\t汽车1的发动机型号:"+car1.engine.model);
	   }
	 }

 

résultat de l'opération :

-----创建汽车1-----
汽车1款式:1	汽车1的发动机型号:1
----汽车1--克隆-->汽车2----
汽车2款式:2	汽车2的发动机型号:2
汽车1款式:1	汽车1的发动机型号:2

 

D'après les résultats d'exécution, on peut constater que la copie superficielle (clone superficiel) copie uniquement l'objet considéré, mais pas l'objet auquel il fait référence.
Par conséquent, lorsque le modèle de moteur de la voiture 2 est défini sur 2 , le modèle de moteur de la voiture 1 passe également de 1 à 2 .

Parce que la voiture 1 et la voiture 2 utilisent en réalité le même moteur

 

Copie profonde (clonage profond) :

Comment mettre en œuvre la copie profonde (clonage profond) ? Modifier la classe de voiture et la classe de moteur de voiture :

 

Catégorie automobile :

/*
 * 深克隆
 */
public class Car implements Cloneable {
	
	public int type;

//	引用的其他对象
	public Engine engine;

	public Object clone() {

		Car temp = null;
		try {

//			先把自己本身复制
			temp = (Car) super.clone();
			
//			为了实现深度克隆,需要将对其他对象(在这里是engine)的引用都复制过去。
			temp.engine = (Engine) engine.clone();
		} catch (CloneNotSupportedException e) {
			// should never happen
		}

		return temp;
	}
}

 

Type de moteur:

public class Engine implements Cloneable {
	public int model;

	/**
	 * 为了实现深度克隆,需要给在Lay1中被应用的对象lay2)也提供一个自己克隆自身的方法
	 */
	public Object clone() {
		Object clone = null;
		try {
			clone = super.clone();
		} catch (CloneNotSupportedException e) {

		}
		return clone;
	}

}

 

Les appels clients restent inchangés.

 

résultat de l'opération :

-----创建汽车1-----
汽车1款式:1	汽车1的发动机型号:1
----汽车1--克隆-->汽车2----
汽车2款式:2	汽车2的发动机型号:2
汽车1款式:1	汽车1的发动机型号:1

 

Selon les résultats d'exécution, on peut constater que la copie profonde (clonage profond) copie tous les objets référencés par l'objet à copier.

Par conséquent, lorsque le modèle de moteur de la voiture 2 est défini sur 2 , le modèle de moteur de la voiture 1 est toujours 1, sans changement .

Parce que la Voiture 1 et la Voiture 2 ont deux moteurs différents.

 

Utilisez la sérialisation pour effectuer une copie complète (clonage profond) :

 

Voiture

Implémentation de l'interface de sérialisation et utilisation d'objets de lecture et d'écriture dans les flux.

 

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

/*
 * 汽车类
 * 
 * 序列化的方式实现深克隆(deep clone)
 */
public class Car implements Serializable {

	/**
	 * serialVersionUID 
	 */
	private static final long serialVersionUID = 1859639569305572020L;

//	汽车款式
	public int type;

//  引用的其他对象,汽车发动机
	public Engine engine;

	public Object clone() {

		try {

//			将对象写到流里,把对象写到流里的过程是串行化(Serilization)过程

			ByteArrayOutputStream bo = new ByteArrayOutputStream();
			ObjectOutputStream oo;

			oo = new ObjectOutputStream(bo);

			oo.writeObject(this);

//			从流里读出来,把对象从流中读出来的并行化(Deserialization)过程
			ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
			ObjectInputStream oi = new ObjectInputStream(bi);
			return (oi.readObject());

		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			return null;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			return null;
		}
	}
}

 

 

Catégorie de moteur automobile :

 

import java.io.Serializable;

public class Engine implements Cloneable, Serializable {

	/**
	 * Car对象以及对象内部所有引用到的对象engine都是可串行化的
	 */
	private static final long serialVersionUID = -6228724315977120960L;

	public int model;

}

 

 

Les appels clients restent inchangés.

 

résultat de l'opération :

-----创建汽车1-----
汽车1款式:1	汽车1的发动机型号:1
----汽车1--克隆-->汽车2----
汽车2款式:2	汽车2的发动机型号:2
汽车1款式:1	汽车1的发动机型号:1

 

Selon les résultats en cours, on peut constater que la copie approfondie (clonabilité) est également obtenue grâce à la sérialisation.

Par conséquent, lorsque le modèle de moteur de la voiture 2 est défini sur 2 , le modèle de moteur de la voiture 1 est toujours 1, sans changement .

Parce que la Voiture 1 et la Voiture 2 ont deux moteurs différents.

Je suppose que tu aimes

Origine blog.csdn.net/louis_lee7812/article/details/83778148
conseillé
Classement