For the decorator design pattern in the weather system, I will simplify content in the console app instead of .Net.
The first task is we want to add a page that takes the country's name and gives the current weather in this country so we will make a list that contains all-weather countries as DB like this,
- public class Weather {
- public string WeatherNow {
- get;
- set;
- }
- public string Country {
- get;
- set;
- }
- }
- public class WeatherDB {
- public static IList < Weather > Weathers = new List < Weather > () {
- new Weather {
- WeatherNow = "Hot", Country = "US"
- }, new Weather {
- WeatherNow = "Cold", Country = "UK"
- }, new Weather {
- WeatherNow = "Moderate", Country = "EG"
- }
- };
- }
and IWeatherSerivce,
- public interface IWeatherService
- {
- string GetWeather(string country);
- }
and add WeatherService to implement the IWeatherService
- public class WeatherService: IWeatherService {
- public string GetWeather(string country) {
- return WeatherDB.Weathers.FirstOrDefault(a => a.Country == country)?.WeatherNow;
- }
- }
and in program.cs call WeatherService
- IWeatherService weatherService = new WeatherService();
- Console.WriteLine(weatherService.GetWeather("US"));
Second Task: is to log data. When client ask for weather we can do logging in the same implementation in GetWeather in WeatherService but we will violate single responsibility principle and open closed principle so we will add decorator class that implements IWeatherSerivce and composes IWeatherSerivce in the constructor like this.
- public class LoggingService: IWeatherService {
- private readonly IWeatherService weatherService;
- public LoggingService(IWeatherService weatherService) {
- this.weatherService = weatherService;
- }
- public string GetWeather(string country) {
- var weather = weatherService.GetWeather(country);
- Console.WriteLine($ "Logging Info: Weather Now in {country} is {weather}");
- return weather;
- }
- }
and so in program.cs we will call LoggingService
- #region WeatherService
- IWeatherService weatherService = new WeatherService();
- Console.WriteLine(weatherService.GetWeather("US"));
- #endregion
- Console.WriteLine("******************************");
- #region LoggingService
- IWeatherService weatherLogging = new LoggingService(weatherService);
- Console.WriteLine(weatherLogging.GetWeather("UK"));
- #endregion
The third task is we want to cache result from client so we will and another decorator class that implements IWeatherSerivce like Logging,
- public class CachingWeatherService: IWeatherService {
- private readonly IWeatherService weatherService;
- public CachingWeatherService(IWeatherService weatherService) {
- this.weatherService = weatherService;
- }
- public string GetWeather(string country) {
- var weather = weatherService.GetWeather(country);
- Console.WriteLine($ "Caching Weather in Memory Info: Weather Now in {country} is {weather}");
- return weather;
- }
- }
and call in program.cs,
- #region WeatherService
- IWeatherService weatherService = new WeatherService();
- Console.WriteLine(weatherService.GetWeather("US"));
- #endregion
- Console.WriteLine("******************************");
- #region LoggingService
- IWeatherService weatherLogging = new LoggingService(weatherService);
- Console.WriteLine(weatherLogging.GetWeather("UK"));
- #endregion
- Console.WriteLine("******************************");
- #region CachingService
- IWeatherService weatherCaching = new CachingWeatherService(weatherLogging);
- Console.WriteLine(weatherCaching.GetWeather("EG"));
- #endregion
- Console.ReadKey();
and so decorator design pattern works like an onion,