Відображення із наслідуванням (шаблон проєктування) — Вікіпедія

Відображення із наслідуванням (англ. 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);     } } 

Див. також[ред. | ред. код]

Джерела[ред. | ред. код]