Близнюки (шаблон проєктування)
Перейти до навігації
Перейти до пошуку
Близнюки — патерн проєктування, що дозволяє імітувати множинне наслідування у мовах програмування, які цього не підтримують.
Нехай дано два класи, які потрібно успадкувати
public class ListBox
{
public virtual void Render()
{
System.Console.WriteLine("Render list box");
}
}
public class UserCollection
{
public virtual void GetUsers()
{
System.Console.WriteLine("Return collection of users");
}
}
Тоді у батьківському класі реалізуємо класи спадкоємці як внутрішні класи:
public class UserListBox
{
private readonly string _callerName = "UserListBox";
// батьківський клас містить посилання на кожного із нащадків
private readonly InnerUserCollection _userCollection;
public UserListBox()
{
_userCollection = new InnerUserCollection(this);
}
// батьківський клас реалізовує поведінку всіх класів, що наслідує
public static implicit operator UserCollection(UserListBox userListBox) => userListBox._userCollection;
private class InnerUserCollection : UserCollection
{
// кожний спадкоємець містить посилання на батьківський клас
private readonly UserListBox _parent;
public InnerUserCollection(UserListBox parent)
{
this._parent = parent;
}
public override void GetUsers()
{
// доступ до приватних членів батьківського класу
System.Console.WriteLine(_parent._callerName);
base.GetUsers();
}
}
}
Приклад реалізації на мові С#
namespace TwinPattern
{
// класи для наслідування
public class ListBox
{
public virtual void Render()
{
System.Console.WriteLine("Render list box");
}
}
public class UserCollection
{
public virtual void GetUsers()
{
System.Console.WriteLine("Return collection of users");
}
}
// наслідування класів відбувається через реалізацію "близнюків"
public class UserListBox
{
private readonly string _callerName = "UserListBox";
private readonly InnerUserCollection _userCollection;
private readonly InnerListBox _listBox;
public UserListBox()
{
_userCollection = new InnerUserCollection(this);
_listBox = new InnerListBox(this);
}
// "наслідування" декількох класів
public static implicit operator UserCollection(UserListBox userListBox) => userListBox._userCollection;
public static implicit operator ListBox(UserListBox userListBox) => userListBox._listBox;
private class InnerUserCollection : UserCollection
{
private readonly UserListBox _parent;
public InnerUserCollection(UserListBox parent)
{
this._parent = parent;
}
public override void GetUsers()
{
System.Console.WriteLine(_parent._callerName);
base.GetUsers();
}
}
private class InnerListBox : ListBox
{
private readonly UserListBox _parent;
public InnerListBox(UserListBox parent)
{
this._parent = parent;
}
public override void Render()
{
System.Console.WriteLine(_parent._callerName);
base.Render();
}
}
}
class Program
{
static void RenderListBox(ListBox listBox)
{
listBox.Render();
}
static void GetUsers(UserCollection userCollection)
{
userCollection.GetUsers();
}
static void Main(string[] args)
{
UserListBox userListBox = new UserListBox();
// "наслідування" декількох класів
RenderListBox(userListBox);
GetUsers(userListBox);
}
}
}