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

6.7 KiB

sidebar_position title
7 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:

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:

...

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);
}

...
...

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 Single-Responsibility: each class should have only one responsibility.

  • Principle of Open-Closed: the software units must be able to be extended without having to modify their behavior.

  • Principle of Liskov Substitutions: a derived class must always be usable instead of its base class.

  • Principle of Interface-Segregation: the interfaces must be perfectly adapted to the needs of the customers who access them.

  • Principle of Dependency-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.