Відображення із наслідуванням (шаблон проєктування)
Відображення із наслідуванням (англ. Inheritance Mappers) — шаблон проєктування, який описую структуру класів відображення ієрархії наслідування.
Опис[ред. | ред. код]
При роботі із ієрархією об'єктів, які реалізують наслідування, необхідно зменшити об'єм коду, який використовується для запису і читання зі сховища, а також надати абстрактні та конкретні методи для роботи із даними.
Не зважаючи на те який спосіб наслідування реалізований зі сховищем (або образу декілька) опишемо структуру яка однакова для всіх.
Реалізація[ред. | ред. код]
Нехай дана ієрархія об'єктів.
public class Player
{
public string Name { get; set; }
}
class Footballer : Player
{
public string Club { get; set; }
}
class Cricketer : Player
{
public int BattingAverage { get; set; }
}
Опишемо абстрактний клас для відображення зі структури в пам'яті до доменного об'єкта.
internal class AbstractMapper
{
public object Find(int id)
{
var row = FindRow(id);
var domainObject = CreateDomainObject();
return PopulateDomainObject(row, domainOjbect);
}
public void Insert(object domainObject)
{
var dataObject = CreateDataObject();
var row = PopulateTableObject(domainObject, dataObject);
db.Insert(row);
}
public void Update(object domainObject)
{
var id = GetId(domainObject);
var dataObject = FindRow();
var row = PopulateTableObject(domainObject, dataObject);
db.Update(row);
}
public void Delete(object domainObject)
{
var row = FindRow(id);
db.Delete(row);
}
protected abstract object GetId(object domainObject);
protected abstract object FindRow(int id);
protected abstract object CreateDomainObject();
protected abstract object CreateDataObject();
protected abstract object PopulateDomainObject(object row, object domainObject);
protected abstract object PopulateTableObject(object domainObject, object tableObject);
}
Кожний клас ієрархії повинний реалізувати свою логіку відображення.
internal class PlayerMapper : AbstractMapper
{
protected object FindRow(int id)
{
return db.Find(id) as PlayerTable;
}
protected object CreateDomainObject(int id)
{
return new Player();
}
protected object PopulateDomainObject(object row, object domainObject)
{
var playerDataRow = row as PlayerTable;
var playerDomainObject = domainObject as Player;
playerDomainObject.Name = playerDataRow.Name;
return playerDomainObject;
}
. . .
}
Класи відображення наслідують у тому ж порядку, що і оригінальна ієрархія та при потребі перевикористовують логіку.
internal class FootballerMapper : PlayerMapper
{
protected override object PopulateDomainObject(object row, object domainObject)
{
var footballerDataRow = base.PopulateDomainObject(row, domainObject) as FootballerMapper;
footballerDataRow.Name = (row as FootballerTable).Club;
return footballerDataRow;
}
. . .
}
Заховаємо вищеописані класи за фасадом, який буде доступний користувачу.
class Mapper
{
private Dictionary<Type, AbstractMapper> mappers = new Dictionary<Type, AbstractMapper>();
// метод реєстрації класів відображення
public void RegisterMapper(Type type, AbstractMapper mapper)
{
mappers[type] = mapper;
}
private AbstractMapper GetMapper(object domainObject)
{
return mappers[domainObject.GetType()];
}
public object Find(int id)
{
foreach (var mapper in mappers.Values)
{
var domainObject = mapper.Find(id);
if (domainObject != null) return domainObject;
}
}
public void Insert(object domainObject)
{
// делегуємо роботу відповідним класам відображення
GetMapper(domainObject).Insert(domainObject);
}
public void Update(object domainObject)
{
GetMapper(domainObject).Update(domainObject);
}
public void Delete(object domainObject)
{
GetMapper(domainObject).Delete(domainObject);
}
}
Див. також[ред. | ред. код]
- Успадкування (програмування)
- Наслідування з однією таблицею
- Наслідування з таблицею для кожного класу
- Наслідування з таблицею для кожного конкретного класу
Джерела[ред. | ред. код]
- Inheritance Mappers [Архівовано 9 серпня 2020 у Wayback Machine.]