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.
<br> public class BoardGameService<br> {<br> public static List boardGameList = new List<br> {<br> new BoardGame<br> {<br> Id = 1, Name = "Catan", Active = true<br> },<br> new BoardGame<br> {<br> Id = 2, Name = "Gaia", Active = true<br> },<br> };</p> <p> public BoardGame Get(int boardGameId)<br> {<br> return boardGameList.FirstOrDefault(x => x.Id == boardGameId);<br> }</p> <p> public void Add(BoardGame boardGame)<br> {<br> boardGameList.Add(boardGame);<br> }</p> <p> public void Delete(int boardGameId)<br> {<br> var boardGame = boardGameList.FirstOrDefault(x => x.Id == boardGameId);<br> if (boardGame != null)<br> boardGame.Active = false;<br> }<br> }<br>
Jak widać, wykorzystujemy tutaj obiekt modelu BoardGame
<br> public class BoardGame<br> {<br> public int Id { get; set; }<br> public string Name { get; set; }<br> public bool Active { get; set; }<br> }<br>
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:
<br> public interface INewBoardGameService<br> {<br> string GetBoardGameName(int boardGameId);<br> NewBoardGame GetNewBoardGame(int boardGameId);<br> void AddBoardGame(NewBoardGame newBoardGame);<br> void DeleteBoardGame(int boardGameId);<br> }<br>
Wspomniany model NewBoardGame różni się od BoardGame jedną właściwością – IsDeleted:
<br> public class NewBoardGame<br> {<br> public int Id { get; set; }<br> public string Name { get; set; }<br> public bool IsDeleted { get; set; }<br> }<br>
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:
<br> public string GetBoardGameName(int boardGameId)<br> {<br> var boardGame = Get(boardGameId);<br> if (boardGame != null)<br> return boardGame.Name;<br> return string.Empty;<br> }<br>
- 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:
<br> public NewBoardGame GetNewBoardGame(int boardGameId)<br> {<br> var boardGame = Get(boardGameId);<br> return new NewBoardGame<br> {<br> Id = boardGame.Id,<br> Name = boardGame.Name,<br> IsDeleted = !boardGame.Active<br> };<br> }<br>
- Metoda AddNewBoardGame
Tutaj jest podobnie – mamy odpowiednik metody w naszej klasie, aczkolwiek znowu nie zgadzają się obiekty modeli. Trzeba napisać odpowiednią logikę:
<br> public void AddBoardGame(NewBoardGame newBoardGame)<br> {<br> var boardGame = new BoardGame<br> {<br> Id = newBoardGame.Id,<br> Name = newBoardGame.Name,<br> Active = !newBoardGame.IsDeleted<br> };<br> Add(boardGame);<br> }<br>
- 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:
<br> public void DeleteBoardGame(int boardGameId)<br> {<br> Delete(boardGameId);<br> }<br>
Ostatecznie cała klasa adaptera będzie wyglądała następująco:
<br> public class BoardGameServiceAdapter : BoardGameService, INewBoardGameService<br> {<br> public void AddBoardGame(NewBoardGame newBoardGame)<br> {<br> var boardGame = new BoardGame<br> {<br> Id = newBoardGame.Id,<br> Name = newBoardGame.Name,<br> Active = !newBoardGame.IsDeleted<br> };<br> Add(boardGame);<br> }</p> <p> public string GetBoardGameName(int boardGameId)<br> {<br> var boardGame = Get(boardGameId);<br> if (boardGame != null)<br> return boardGame.Name;<br> return string.Empty;<br> }</p> <p> public NewBoardGame GetNewBoardGame(int boardGameId)<br> {<br> var boardGame = Get(boardGameId);<br> return new NewBoardGame<br> {<br> Id = boardGame.Id,<br> Name = boardGame.Name,<br> IsDeleted = !boardGame.Active<br> };<br> }</p> <p> public void DeleteBoardGame(int boardGameId)<br> {<br> Delete(boardGameId);<br> }<br> }<br>
Tyle na dzisiaj. W kolejnym wpisie opiszę drugi rodzaj tego wzorca, czyli adapter obiektu.
PS – przykładowy kod można pobrać pod linkiem.
Podoba Ci się to, co tworzę? Chcesz dostawać informacje o:
– wydarzeniach, które organizuję lub wspieram (np. konferencje, meetupy, webinary)
– inicjatywach, które organizuję lub wspieram (np. GeekWeekWro, DevAdventCalendar)
– moich prelekcjach, kursach i szkoleniach
– wyróżnionych artykułach z mojego bloga
0% SPAMu, 100% informacji! Krótko i na temat.
Pingback: Wzorzec adapter – cz. 2 adapter obiektu – programmer-girl