Artykuł

freeimages.com freeimages.com
mar 11 2015
0

Wzorzec template method - przykładowa implementacja w C#

Dobry programista zawsze będzie się starał pisać czytelny kod. Kluczem do sukcesu jest w tym przypadku ciągła refaktoryzacja wsparta wzorcami projektowymi. Wzorce projektowe w wielu przypadkach pozwalają na zapewnienie elastycznych i skalowalnych rozwiązań, a ponadto sprzyjają w tworzeniu unikalnego kodu. Oczywiście nieodpowiednio użyte mogą również zaszkodzić - tak jak inne rzeczy w naszym codziennym życiu;-)

Dlaczego o tym wszystkim piszę? Przyczyna jest bardzo prosta - chciałbym w dzisiejszym wpisie przedstawić kolejny wzorzec typu must have, czy może w tym przypadku bardziej must use.

Template method (po polsku - metoda szablonowa) jest wzorcem niezwykle prostym w użyciu i jednocześnie bardzo użytecznym zarazem, ponieważ pozwala zredukować duplikowany kod do minimum, a czasem nawet do zera. Najwyższa więc pora na krótką prezentację;-)

Idea

Idea wzorca template method jest banalnie prosta - służy on do tworzenia metod szablonowych, które składają się z mniejszych - zmiennych komponentów. Metody szablonowe umieszczamy z reguły w klasie abstrakcyjnej. W tym miejscu tworzymy szkielet takiej metody oraz deklaracje poszczególnych metod składowych, które w niektórych przypadkach mogą zostać od razu zaimplementowane.

W kolejnym kroku tworzymy poszczególne klasy konkretne, które wypełniają odpowiednią treścią składowe metody szablonowej, która sama w sobie z reguły jest niezmienna.

Taka konstrukcja pozwala na rozwiązywanie nawet bardzo złożonych problemów - wystarczy odpowiednio zdekomponować istniejący kod:-)

Przykład praktyczny

Najwyższa pora na prosty przykład. Zacznijmy od klasy abstrakcyjnej:

abstract class AbstractClass
{
	protected abstract void OperationA();
	protected abstract void OperationB();

	protected void OperationC()
	{
		Console.WriteLine("AbstractClass.OperationC");
	}

	protected virtual void OperationD()
	{
		Console.WriteLine("AbstractClass.OperationD");
	}

	public void Run()
	{
		this.OperationA();
		this.OperationB();
		this.OperationC();
		this.OperationD();
	}
}

Nasza klasa składa się z pięciu metod. Najważniejsza jest metoda szablonowa Run, która operuje na czterech składowych. Metody OperationA oraz OperationB są nie zaimplementowane i ich implementacja musi się pojawić w klasach potomnych. Metody OperationC oraz OperationD są już zdefiniowane i istnieje techniczna możliwość przesłonięcia metody OperationD (dzięki zastosowaniu słówka kluczowego Virtual). Możemy oczywiście też korzystać z bazowej implementacji.

Spójrzmy na dwie przykładowe klasy rozszerzające AbstractClass:

class ClassFirst : AbstractClass
{
	protected override void OperationA()
	{
		Console.WriteLine("ClassFirst.OperationA");
	}
	protected override void OperationB()
	{
		Console.WriteLine("ClassFirst.OperationB");
	}

	protected override void OperationD()
	{
		Console.WriteLine("ClassFirst.OperationD");
	}
}

class ClassSecond : AbstractClass
{
	protected override void OperationA()
	{
		Console.WriteLine("ClassSecond.OperationA");
	}
	protected override void OperationB()
	{
		Console.WriteLine("ClassSecond.OperationB");
	}
}

W pierwszym przypadku zaimplementowaliśmy wymagane metody OperationA oraz OperationB, a także nadpisaliśmy metodę OperationD. Drugi przypadek jest bardzo podobny, lecz tym razem ograniczyliśmy się do dwóch pierwszych metod.

Zwieńczeniem całego przykładu jest klasa Program:

class Program
{
	static void Main(string[] args)
	{
		AbstractClass obj = new ClassFirst();
		obj.Run();

		obj = new ClassSecond();
		obj.Run();

		Console.ReadKey();
	}
}

Tworzymy dwa testowe obiekty - po jednym dla każdej z klas, a następnie wywołujemy metodę Run na obu. Efekt można podziwiać w konsoli:

ClassFirst.OperationA
ClassFirst.OperationB
AbstractClass.OperationC
ClassFirst.OperationD
ClassSecond.OperationA
ClassSecond.OperationB
AbstractClass.OperationC
AbstractClass.OperationD

Kilka uwag

Na koniec kilka szybkich uwag, odnośnie użycia metody szablonowej:

  • Metoda szablonowa może przyjmować parametry
  • Poszczególne metody składowe mogą zwracać wartości oraz przyjmować stałe parametry
  • Metody składowe mogą operować na polach klasy
  • Zaleca się niezmienianie treści metody szablonowej

Źródła

Podoba Ci się ten wpis? Powiedz o tym innym!

Send to Kindle

Komentarze

blog comments powered by Disqus