---
sidebar_position: 7
title: Utiliser le Pattern Factory
---

Dans le code de la page `Edit.razor.cs`, nous avons transformé notre item dans le modèle et inversement.

Nous utilisons actuellement ce code seulement dans deux pages, si nous ajoutions un nouveau champ, il faudrait passer sur chaque page afin d'éffectuer les modifications d'assignement.

Nous allons donc utiliser le pattern Factory.

## Création de notre factory

Pour cela créer le dossier `Factories` à la racine du site.

Dans ce dossier créer une nouvelle classe `ItemFactory` et la modifier comme suite :

```csharp title="Factories/ItemFactory.cs"
public static class ItemFactory
{
	public static ItemModel ToModel(Item item, byte[] imageContent)
	{
		return new ItemModel
		{
			Id = item.Id,
			DisplayName = item.DisplayName,
			Name = item.Name,
			RepairWith = item.RepairWith,
			EnchantCategories = item.EnchantCategories,
			MaxDurability = item.MaxDurability,
			StackSize = item.StackSize,
			ImageContent = imageContent
		};
	}

	public static Item Create(ItemModel model)
	{
		return new Item
		{
			Id = model.Id,
			DisplayName = model.DisplayName,
			Name = model.Name,
			RepairWith = model.RepairWith,
			EnchantCategories = model.EnchantCategories,
			MaxDurability = model.MaxDurability,
			StackSize = model.StackSize,
			CreatedDate = DateTime.Now
		};
	}

	public static void Update(Item item, ItemModel model)
	{
		item.DisplayName = model.DisplayName;
		item.Name = model.Name;
		item.RepairWith = model.RepairWith;
		item.EnchantCategories = model.EnchantCategories;
		item.MaxDurability = model.MaxDurability;
		item.StackSize = model.StackSize;
		item.UpdatedDate = DateTime.Now;
	}
}
```

Une factory est toujours `static` c'est à dire qu'elle ne s'instencie jamais, elle peut être considerée comme un convertisseur.

## Utilisation de notre factory

Ouvrir le fichier `Services/DataLocalService.cs` et modifier comme suite :

```csharp title="Services/DataLocalService.cs"
...

public async Task Add(ItemModel model)
{
	...

	// Simulate the Id
	model.Id = currentData.Max(s => s.Id) + 1;

	// Add the item to the current data
	// highlight-next-line
	currentData.Add(ItemFactory.Create(model));

	// Save the image
	var imagePathInfo = new DirectoryInfo($"{_webHostEnvironment.WebRootPath}/images");

	...
}

public async Task Update(int id, ItemModel model)
{
	...

	// Write the file content
	await File.WriteAllBytesAsync(fileName.FullName, model.ImageContent);

	// Modify the content of the item
	// highlight-next-line
	ItemFactory.Update(item, model);

	// Save the data
	await _localStorage.SetItemAsync("data", currentData);
}

...
```

```csharp title="Pages/Edit.razor.cs"
...

protected override async Task OnInitializedAsync()
{
	var item = await DataService.GetById(Id);

	var fileContent = await File.ReadAllBytesAsync($"{WebHostEnvironment.WebRootPath}/images/default.png");

	if (File.Exists($"{WebHostEnvironment.WebRootPath}/images/{itemModel.Name}.png"))
	{
		fileContent = await File.ReadAllBytesAsync($"{WebHostEnvironment.WebRootPath}/images/{item.Name}.png");
	}

	// Set the model with the item
	// highlight-next-line
	itemModel = ItemFactory.ToModel(item, fileContent);
}

...
```

## Notion : Factory Pattern

### Qu’est-ce que le factory pattern ?

Le factory pattern décrit une approche de programmation qui vous permet de créer des objets sans avoir à spécifier la classe exacte de ces objets. 
Cela permet d'échanger l’objet créé de manière souple et pratique. 
Pour la mise en œuvre, les développeurs ont recours au patron de conception fabrique, également appelé factory pattern, qui donne son nom au modèle. 
Cette méthode est soit spécifiée dans une interface et implémentée par une classe enfant, soit implémentée par une classe de base et éventuellement écrasée (par des classes dérivées). 
Le patron se substitue ainsi au constructeur de classe habituel pour détacher la création d’objets des objets eux-mêmes, permettant ainsi de suivre les principes dits SOLID.

:::tip

**Les principes SOLID** sont un sous-ensemble de principes de la programmation orientée objet (POO) qui visent à améliorer le processus de développement des logiciels orientés objet. L’acronyme "SOLID" désigne les cinq principes suivants :

- Principe de **S**ingle-Responsibility : chaque classe ne devrait avoir qu'une seule responsabilité.

- Principe de **O**pen-Closed : les unités logicielles doivent pouvoir être étendues sans avoir à modifier leur comportement.

- Principe de Substitutions de **L**iskov : une classe dérivée doit toujours être utilisable à la place de sa classe de base.

- Principe de **I**nterface-Segregation : les interfaces doivent être parfaitement adaptées aux besoins des clients qui y accèdent.

- Principe de **D**ependency-Inversion : les classes à un niveau d’abstraction supérieur ne devraient jamais dépendre de classes à un niveau d’abstraction inférieur.

:::

### Quel est l’objectif du factory pattern ?

Le factory pattern vise à résoudre un problème fondamental lors de l’instanciation, c’est-à-dire la création d’un objet concret d’une classe, dans la programmation orientée objet : 
**créer un objet directement au sein de la classe**, qui a besoin de cet objet ou devrait l’utiliser,  est possible en principe, mais **très rigide**. 
Il lie la classe à cet objet particulier et rend impossible de modifier l'instanciation indépendamment de la classe. 
Le factory pattern évite un tel code en définissant d'abord une opération distincte pour la création de l'objet : la fabrique. 
Une fois appelée, elle génère l’objet, au lieu du constructeur de classe mentionné plus haut.

### Les avantages et les inconvénients du factory pattern

Dans le factory pattern, l’appel d’une méthode de programme est complètement séparé de l’implémentation de nouvelles classes, ce qui présente certains avantages. 
Cela a notamment un effet sur l’**extensibilité d’un logiciel** : les instances du patron factory ont un degré élevé d’autonomie et permettent d’**ajouter de nouvelles classes** sans que l’application ait à changer de quelque façon que ce soit, parallèlement à l'exécution. 
Il suffit d’implémenter l'interface de l'usine et d'instancier le créateur en conséquence.

Un autre avantage est la bonne testabilité des composants de la fabrique. 
Si une `factory` met en place trois classes, par exemple, leur fonctionnalité peut être testée individuellement et indépendamment de la classe d’appel. 
Dans le cas de ce dernier, il suffit de s’assurer qu’il appelle correctement la `factory`, même si le logiciel est étendu à cette étape ultérieurement. 
La possibilité de donner un nom significatif au patron factory (contrairement à un constructeur de classe) est également bénéfique.

La grande faiblesse du factory pattern est le fait que son implémentation entraîne une forte augmentation des classes incluses. 
Aussi rentable que soit en principe l’approche du factory pattern en ce qui concerne l’extension d'un logiciel, elle est également désavantageuse en ce qui concerne l’effort à fournir : 
si une famille de produits doit être étendue, non seulement l'interface, mais aussi toutes les classes subordonnées de la `factory` doivent être adaptées en conséquence. 
Une bonne planification préalable des types de produits requis est donc indispensable.



