Во-первых, давайте представим способ заваривания кофе и чая:
Чай
1. 把水煮沸
2. 用沸水浸泡茶叶
3. 把茶放到杯子里
кофе
1. 把水煮沸
2. 用沸水冲泡咖啡
3. 把咖啡倒进杯子
4. 加糖和牛奶
Метод заваривания, реализованный с помощью кода Python, выглядит так:
# 茶的制作方法
class Tea:
def prepare_recipe(self):
# 在下边实现具体步骤
self.boil_water()
self.brew_tea_bag()
self.pour_in_cup()
def boil_water(self):
print("Boiling water")
def brew_tea_bag(self):
print("Steeping the tea")
def pour_in_cup(self):
print("Pouring into cup")
# 咖啡的制作方法
class Coffee:
def prepare_recipe(self):
# 在下边实现具体步骤
self.boil_water()
self.brew_coffee_grinds()
self.pour_in_cup()
self.add_sugar_and_milk()
def boil_water(self):
print("Boiling water")
def brew_coffee_grinds(self):
print("Dripping Coffee through filter")
def pour_in_cup(self):
print("Pouring into cup")
def add_sugar_and_milk(self):
print("Adding Sugar and Milk")
Если вы внимательно посмотрите на код с обеих сторон, вы обнаружите, что реализация чая и кофе в основном похожа.prepare_recipe,boil_water,pour_in_cupэти три метода.
问题:Как переделать эти два класса, чтобы сделать код более лаконичным?
Сначала посмотрите на диаграмму классов двух классов:
- в каждом классе
prepare_recipe() boil_water() pour_in_cup()метод. - в каждом классе
prepare_recipe()Методы реализуются по-разному.
теперь поставьprepare_recipe() boil_water() pour_in_cup()Извлекаются три метода для создания родительского классаCoffeineBeverage(),Teaа такжеCoffeeвсе удалось отCoffeineBeverage().
потому что каждый класс
prepare_recipe()Способ реализации разный, т.Teaа такжеCoffeeклассы реализованы отдельноprepare_recipe().问题: Итак, есть ли способprepare_recipe()Тоже абстрактно?
В сравненииTeaа такжеCoffeeизprepare_recipe()Метод обнаружит, что различия между ними в основном заключаются в следующем:
def prepare_recipe(self):
# 相同部分隐藏
# self.boil_water()
self.brew_tea_bag() # 差异1
#self.pour_in_cup()
def prepare_recipe(self):
# 相同部分隐藏
# self.boil_water()
self.brew_coffee_grinds() # 差异1
# self.pour_in_cup()
self.add_sugar_and_milk() # 差异2
Идея реализации здесь состоит в том, чтобы заменить два различия новыми именами методов, и результаты после замены будут следующими:
def prepare_recipe(self):
# 新的实现方法
self.boil_water()
self.brew() # 差异1 使用brew 代替 brew_tea_bag 和 brew_coffee_grinds
self.pour_in_cup()
self.add_condiments() # 差异2 Tea 不需要此方法,可以用空的实现代替
Новая диаграмма классов выглядит следующим образом:
Теперь классTeaа такжеCoffeeНужно только реализовать конкретныеbrew()а такжеadd_condiments()метод. Код реализован следующим образом:
class CoffeineBeverage:
def prepare_recipe(self):
# 新的实现方法
self.boil_water()
self.brew()
self.pour_in_cup()
self.add_condiments()
def boil_water(self):
print("Boiling water")
def brew(self):
# 需要在子类实现
raise NotImplementedError
def pour_in_cup(self):
print("Pouring into cup")
def add_condiments(self):
# 这里其实是个钩子方法,子类可以视情况选择是否覆盖
# 钩子方法是一个可选方法,也可以让钩子方法作为某些条件触发后的动作
pass
# 茶的制作方法
class Tea(CoffeineBeverage):
def brew(self):
# 父类中声明了 raise NotImplementedError,这里必须要实现此方法
print("Steeping the tea")
# Tea 不需要 add_condiments 方法,所以这里不需要实现
# 咖啡的制作方法
class Coffee(CoffeineBeverage):
def brew(self):
# 父类中声明了 raise NotImplementedError,这里必须要实现此方法
print("Dripping Coffee through filter")
def add_condiments(self):
print("Adding Sugar and Milk")
шаблонный метод
Вышеупомянутая абстракция использует метод шаблона. Шаблонные методы определяют шаги алгоритма и позволяют подклассам предоставлять реализации для одного или нескольких шагов. В этом примереprepare_recipeявляется шаблонным методом.
定义:Жрецы шаблонных методов определяют скелет алгоритма в методе, откладывая при этом некоторые шаги на подклассы. Шаблонные методы позволяют подклассам переопределять определенные шаги в алгоритме без изменения структуры алгоритма.
преимущество
- Используйте шаблонные методы, чтобы максимизировать повторное использование кода
- Подклассам нужно только реализовать свои собственные методы, чтобы уменьшить связь между алгоритмом и реализацией.
Голливудские принципы
Шаблонный метод использует принцип,好莱坞原则.
好莱坞原则, не звони мне, я позвоню тебе.
В приведенном выше примере CoffeeineBeverage — это высокоуровневый компонент, Coffee и Tea — низкоуровневые компоненты, и между ними не будет вызываться абстрактный класс (CoffeineBeverage).
Пример 🌰
Часть проверки формы стороннего пакета проверки формы Python wtforms использует шаблон метода шаблона. в полевом классеvalidateметод является методом шаблона, в этом методе будет вызыватьсяpre_validate,_run_validation_chain,post_validateметоды для проверки формы, которые также могут быть повторно реализованы в подклассах. Конкретная реализация может относиться к следующему исходному коду.
Адрес источника:GitHub.com/WT формы/WTF…
Ссылка на ссылку
Пример в этой статье взят из "Шаблоны проектирования Head First".
Наконец, поблагодарите мою девушку за ее поддержку и терпимость, чем ❤️
Вы также можете ввести следующие ключевые слова в официальном аккаунте, чтобы получить исторические статьи:公号&小程序 | 设计模式 | 并发&协程