在Python中使用 Facade 设计模式实现天气预报
外观设计模式是Python中的设计模式,它为复杂的子系统提供简单的接口。当我们观察周围的世界时,我们总能找到外观设计模式。汽车就是最好的例子:您不需要了解发动机的工作原理。要操作发动机,您将获得一组简单的界面,例如转动点火钥匙启动发动机、使用方向盘转动车轮等。让我们来看看外观设计模式的优点。它们如下:
- 保持客户端和子系统之间的松散耦合。
- 更易于使用和测试
- 为客户端代码提供更好更清晰的API
- 它用一个简单的接口包装了一个复杂的子系统
天气预报实施
让我们进入实现部分。在这个应用程序中,我们获取一个城市的当前温度。为此,我们使用来自 openweathermap.org 资源的可用 API。在这里,在不使用外观设计模式的情况下,客户端必须经历许多复杂的任务,例如 API 调用、解析和检索必要的数据以及从 Kelvin 转换为 Celcius。如果客户端只需要调用一种方法来获取当前温度,那就更容易了。这就是我们通过外观设计模式实现的目标。
在进入源代码之前,让我们先看看代码设计模式。
在上图中,我们有一个由四个模块组成的子系统。如果客户端直接使用这些模块,就会失去灵活性。这是因为,如果更改了任何模块,则需要修改客户端代码,这会增加额外的复杂性。在使用外观设计模式时,客户端使用外观,其中外观调用子模块并将必要的详细信息返回给客户端。这种设计基于分解原理,将复杂的系统拆分为更小、更简单的子系统。
让我们看看每个模块的功能。
- WeatherRetriever类向天气 API 端点发出请求并返回预测数据。
- Crawler类抓取从 WeatherRetriever 类返回的数据,以 JSON 格式对其进行解码,并获取温度。
- WeatherForecast类负责存储温度数据。
- 最后, Converter类将温度从开尔文转换为摄氏度
Python3
import urllib
import urllib.request
import urllib.parse
import json
class WeatherRetriever(object):
def __init__(self):
self.api_url = 'https://samples.openweathermap.org/data/2.5/\
weather?q={},{}&appid=439d4b804bc8187953eb36d2a8c26a02'
# takes input (city and country), produces a URL string,
# generate HTTP request, and returns the data.
def fetch_weather_data(self, city, country):
city = urllib.parse.quote(city)
url = self.api_url.format(city, country)
return urllib.request.urlopen(url).read()
class Crawler(object):
def crawl_weather_data(self, weather_data):
data = json.loads(weather_data)
# fetch the current temperature
temp_data = data['main']['temp']
return temp_data
class Converter(object):
""" converts the temperature from kelvin to celcius """
def from_kelvin_to_celcius(self, kelvin):
return kelvin - 273.15
class WeatherForecast(object):
def __init__(self, data):
self.temperature = data
class FacadeDesign(object):
def get_forecast(self, city, country):
weather_retriever = WeatherRetriever()
weather_data = weather_retriever.fetch_weather_data(city, country)
crawl = Crawler()
crawl_data = crawl.crawl_weather_data(weather_data)
weather = WeatherForecast(crawl_data)
converter = Converter()
temp_celcius = converter.from_kelvin_to_celcius(weather.temperature)
return temp_celcius
if __name__ == '__main__':
facadeDesign = FacadeDesign()
print("So today's forecast is about ",
facadeDesign.get_forecast('London', 'uk'), "degrees")
输出:
So today’s forecast is about 7.170000000000016 degrees
外观设计模式提供了一个更高级别的接口,可以简化子系统的使用。外观设计没有添加任何新功能,相反,它充当了一个包装器,为访问复杂子系统提供了灵活性。