Близнюки (шаблон проєктування)

Близнюки — патерн проєктування, що дозволяє імітувати множинне наслідування у мовах програмування, які цього не підтримують.

Опис

Нехай дано два класи, які потрібно успадкувати

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

Реалізація

C#

Приклад реалізації на мові С#
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);
		}
	}
}

Див.також

Prefix: a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9

Portal di Ensiklopedia Dunia

Kembali kehalaman sebelumnya