You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Blazor/Documentation/docusaurus/docs/edit-item/use-factory-pattern.md

178 lines
6.7 KiB

---
sidebar_position: 7
title: Use the Pattern Factory
---
In the code of the `Edit.razor.cs` page, we have transformed our item into the model and vice versa.
We currently use this code only in two pages, if we added a new field, it would be necessary to pass on each page in order to carry out the modifications of assignment.
We are therefore going to use the Factory pattern.
## Creation of our factory
To do this, create the `Factories` folder at the root of the site.
In this folder create a new `ItemFactory` class and modify it as follows:
```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;
}
}
```
A factory is always `static` ie it never instantiates, it can be considered as a converter.
## Using our factory
Open the `Services/DataLocalService.cs` file and modify as follows:
```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);
}
...
```
## Concept: Factory Pattern
### What is the factory pattern?
The factory pattern describes a programming approach that allows you to create objects without having to specify the exact class of those objects.
This makes exchanging the created item flexible and convenient.
For the implementation, developers use the factory design pattern, also called factory pattern, which gives its name to the model.
This method is either specified in an interface and implemented by a child class, or implemented by a base class and possibly overridden (by derived classes).
The pattern thus replaces the usual class constructor to detach the creation of objects from the objects themselves, thus making it possible to follow the so-called SOLID principles.
:::tip
**SOLID Principles** are a subset of object-oriented programming (OOP) principles that aim to improve the object-oriented software development process. The acronym "SOLID" refers to the following five principles:
- Principle of **S**ingle-Responsibility: each class should have only one responsibility.
- Principle of **O**pen-Closed: the software units must be able to be extended without having to modify their behavior.
- Principle of **L**iskov Substitutions: a derived class must always be usable instead of its base class.
- Principle of **I**nterface-Segregation: the interfaces must be perfectly adapted to the needs of the customers who access them.
- Principle of **D**ependency-Inversion: classes at a higher level of abstraction should never depend on classes at a lower level of abstraction.
:::
### What is the purpose of the factory pattern?
The factory pattern aims to solve a fundamental problem during instantiation, i.e. the creation of a concrete object of a class, in object-oriented programming:
**creating an object directly within the class**, which needs this object or should use it, is possible in principle, but **very rigid**.
It binds the class to that particular object and makes it impossible to modify the instantiation independent of the class.
The factory pattern avoids such code by first defining a separate operation for creating the object: the factory.
When called, it generates the object, instead of the class constructor mentioned above.
### The pros and cons of the factory pattern
In the factory pattern, calling a program method is completely separate from implementing new classes, which has some advantages.
This has an effect in particular on the **extensibility of software**: instances of the factory pattern have a high degree of autonomy and allow you to **add new classes** without the application having to change in any way, alongside execution.
Just implement the factory interface and instantiate the creator accordingly.
Another advantage is the good testability of the factory components.
If a `factory` implements three classes, for example, their functionality can be tested individually and independently of the calling class.
In the case of the latter, you just need to make sure that it calls the `factory` correctly, even if the software is extended to this step later.
The ability to give a meaningful name to the factory pattern (as opposed to a class constructor) is also beneficial.
The great weakness of the factory pattern is the fact that its implementation leads to a large increase in the classes included.
As cost-effective as the factory pattern approach is in principle when it comes to extending software, it is also disadvantageous when it comes to effort:
if a product family is to be extended, not only the interface, but also all subordinate classes of the `factory` must be adapted accordingly.
Good advance planning of the types of products required is therefore essential.