C# · Programowanie · Wzorce projektowe

Wzorzec adapter – cz. 1 adapter klasy

Cel

W książkach można przeczytać, że głównym celem tego wzorca jest zaadaptowanie (przystosowanie) istniejącej klasy do formy, którą oczekuje klient. Klientem w tym przypadku jest dowolny obiekt, który wywołuje nasz kod i wymaga odpowiedniego interfejsu.

Teoria może być łatwa, ale trzeba jeszcze umieć zastosować ją w praktyce. Stwórzmy więc przykładową klasę BoardGameService.

public class BoardGameService
{
	public static List boardGameList = new List
	{
		new BoardGame
		{
			Id = 1, Name = "Catan", Active = true
		},
		new BoardGame
		{
			Id = 2, Name = "Gaia", Active = true
		},
	};

	public BoardGame Get(int boardGameId)
	{
		return boardGameList.FirstOrDefault(x => x.Id == boardGameId);
	}

	public void Add(BoardGame boardGame)
	{
		boardGameList.Add(boardGame);
	}

	public void Delete(int boardGameId)
	{
		var boardGame = boardGameList.FirstOrDefault(x => x.Id == boardGameId);
		if (boardGame != null)
			boardGame.Active = false;
	}
}

Jak widać, wykorzystujemy tutaj obiekt modelu BoardGame

public class BoardGame
{
	public int Id { get; set; }
	public string Name { get; set; }
	public bool Active { get; set; }
}

Adapter klasy

Jeśli klient definiuje swoje wymagania na podstawie jakiegoś interfejsu, sprawa jest całkiem prosta. Wystarczy dostarczyć klasę, która:

  • implementuje ten interfejs,
  • dziedziczy po istniejącej klasie

W naszym przykładzie załóżmy, że klient chciałby, żeby interfejs INewBoardGameService wyglądał następująco:

public interface INewBoardGameService
{
	string GetBoardGameName(int boardGameId);
	NewBoardGame GetNewBoardGame(int boardGameId);
	void AddBoardGame(NewBoardGame newBoardGame);
	void DeleteBoardGame(int boardGameId);
}

Wspomniany model NewBoardGame różni się od BoardGame jedną właściwością – IsDeleted:

public class NewBoardGame
{
	public int Id { get; set; }
	public string Name { get; set; }
	public bool IsDeleted { get; set; }
}

Przeanalizujmy po kolei przez wszystkie metody:

  • Metoda GetBoardGameName

Nie mamy odpowiednika tej metody w naszej klasie. Ale możemy stworzyć logikę, która pobiera obiekt BoardGame i zwraca tylko parametr Name:

public string GetBoardGameName(int boardGameId)
{
	var boardGame = Get(boardGameId);
	if (boardGame != null)
		return boardGame.Name;
	return string.Empty;
}
  • Metoda GetNewBoardGame

Mamy odpowiednik tej metody w naszej klasie. Jedyny problem to to, że jest zwracany obiekt BoardGame, a nie NewBoardGame. Co możemy z tym zrobić? Możemy napisać odpowiednią logikę w metodzie adaptera:

public NewBoardGame GetNewBoardGame(int boardGameId)
{
	var boardGame = Get(boardGameId);
	return new NewBoardGame
	{
		Id = boardGame.Id,
		Name = boardGame.Name,
		IsDeleted = !boardGame.Active
	};
}
  • Metoda AddNewBoardGame

Tutaj jest podobnie – mamy odpowiednik metody w naszej klasie, aczkolwiek znowu nie zgadzają się obiekty modeli. Trzeba napisać odpowiednią logikę:

public void AddBoardGame(NewBoardGame newBoardGame)
{
	var boardGame = new BoardGame
	{
		Id = newBoardGame.Id,
		Name = newBoardGame.Name,
		Active = !newBoardGame.IsDeleted
	};
	Add(boardGame);
}
  • Metoda DeleteBoardGame

W tym przypadku metody pokrywają się. Nie trzeba pisać logiki obsługującej. Metoda adaptera będzie wyglądała następująco:

public void DeleteBoardGame(int boardGameId)
{
	Delete(boardGameId);
}

Ostatecznie cała klasa adaptera będzie wyglądała następująco:

public class BoardGameServiceAdapter : BoardGameService, INewBoardGameService
{
	public void AddBoardGame(NewBoardGame newBoardGame)
	{
		var boardGame = new BoardGame
		{
			Id = newBoardGame.Id,
			Name = newBoardGame.Name,
			Active = !newBoardGame.IsDeleted
		};
		Add(boardGame);
	}

	public string GetBoardGameName(int boardGameId)
	{
		var boardGame = Get(boardGameId);
		if (boardGame != null)
			return boardGame.Name;
		return string.Empty;
	}

	public NewBoardGame GetNewBoardGame(int boardGameId)
	{
		var boardGame = Get(boardGameId);
		return new NewBoardGame
		{
			Id = boardGame.Id,
			Name = boardGame.Name,
			IsDeleted = !boardGame.Active
		};
	}

	public void DeleteBoardGame(int boardGameId)
	{
		Delete(boardGameId);
	}
}

Tyle na dzisiaj. W kolejnym wpisie opiszę drugi rodzaj tego wzorca, czyli adapter obiektu.

PS – przykładowy kod można pobrać pod linkiem.

Jedna myśl na temat “Wzorzec adapter – cz. 1 adapter klasy

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Wyloguj /  Zmień )

Zdjęcie na Google+

Komentujesz korzystając z konta Google+. Wyloguj /  Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Wyloguj /  Zmień )

Zdjęcie na Facebooku

Komentujesz korzystając z konta Facebook. Wyloguj /  Zmień )

Connecting to %s