AI越来越火热,人工智能已然成风!而人工智能最重要是各种算法,因此机器学习越来越受到追捧,算法越来越被重视。
作为一个算法的研究者,写出一手高级算法当然是令人兴奋的一件事!但你是否有时会有这种感觉:
这个时候,让你的算法具有更好通用性、拓展性就显得极为重要!因此,你必须要掌握几个重要的设计模式来解决这些问题。今天介绍一种在算法领域中应用最广泛的设计模式——策略模式。
定义一系列算法,将每个算法都封装起来,并且使他们之间可以相互替换。策略模式使算法可以独立于使用它的用户而变化。
策略模式是对算法、规则的一种封装。它具有以下的优点:
假设有这样一个应用场景:
有一Person类,有年龄(age),体重(weight),身高(height)三个属性。现要对Person的一组对象进行排序,但并没有确定根据什么规则来排序,有时需要根据年龄进行排序,有时需要根据身高进行排序,有时可能是根据身高和体重的综合情况来排序,还有可能……
通过对这个应用场景进行分析,我们会发现,这里需要有多种排序算法,而且需要动态地在这几种算法中进行选择,在未来可能还会添加一新的排序规则……
怎样让我们的排序算法更加的灵活,以适应各种各样的排序规则呢?这里我们就要用到策略模式。来,我们一起看一下具体的代码实现吧。
源码示例:
class Person:
"人类"
def __init__(self, name, age, weight, height):
self.name = name
self.age = age
self.weight = weight
self.height = height
def showMysef(self):
print(self.name + " " + str(self.age) + " years old, " + str(self.weight) + "kg, " + str(self.height) + "m.")
class ICompare:
"比较算法"
def comparable(self, person1, person2):
"person1 > person2 返回值>0,person1 == person2 返回0, person1 < person2 返回值小于0"
pass
class CompareByAge(ICompare):
"通过年龄排序"
def comparable(self, person1, person2):
return person1.age - person2.age
class CompareByHeight(ICompare):
"通过身高进行排序"
def comparable(self, person1, person2):
return person1.height - person2.height
class SortPerson:
"Person的排序类"
def __init__(self, compare):
self.__compare = compare
def sort(self, personList):
"排序算法,这里采用最简单的冒泡排序"
n = len(personList)
for i in range(0, n-1):
for j in range(0, n-i-1):
if(self.__compare.comparable(personList[j], personList[j+1]) > 0):
tmp = personList[j]
personList[j] = personList[j+1]
personList[j+1] = tmp
j += 1
i += 1
测试代码:
def testSortPerson():
personList = [
Person("Tony", 2, 54.5, 0.82),
Person("Jack", 31, 74.5, 1.80),
Person("Nick", 54, 44.5, 1.59),
Person("Eric", 23, 62.0, 1.78),
Person("Helen", 16, 45.7, 1.60)
]
sorter0 = SortPerson(CompareByAge())
sorter0.sort(personList)
print("根据年龄进行排序后的结果:")
for person in personList:
person.showMysef()
print()
sorter1 = SortPerson(CompareByHeight())
sorter1.sort(personList)
print("根据身高进行排序后的结果:")
for person in personList:
person.showMysef()
输出结果:
根据年龄进行排序后的结果:
Tony 2 years old, 54.5kg, 0.82m.
Helen 16 years old, 45.7kg, 1.6m.
Eric 23 years old, 62.0kg, 1.78m.
Jack 31 years old, 74.5kg, 1.8m.
Nick 54 years old, 44.5kg, 1.59m.
根据身高进行排序后的结果:
Tony 2 years old, 54.5kg, 0.82m.
Nick 54 years old, 44.5kg, 1.59m.
Helen 16 years old, 45.7kg, 1.6m.
Eric 23 years old, 62.0kg, 1.78m.
Jack 31 years old, 74.5kg, 1.8m.
看到这,一些熟悉Python的同学肯定要吐槽了!Python是一个简洁明了的语言,使用十几行代码就能解决的问题(如下面的实现代码),为什么要写上面这一大堆的东西。
from operator import itemgetter,attrgetter
def testPersonListInPython():
"用Python的方式对Person进行排序"
personList = [
Person("Tony", 2, 54.5, 0.82),
Person("Jack", 31, 74.5, 1.80),
Person("Nick", 54, 44.5, 1.59),
Person("Eric", 23, 62.0, 1.78),
Person("Helen", 16, 45.7, 1.60)
]
# 使用使用operator模块根据年龄进行排序
print("根据年龄进行排序后的结果:")
sortedPerons = sorted(personList, key = attrgetter('age'))
for person in sortedPerons:
person.showMysef()
print()
print("根据身高进行排序后的结果:")
sortedPerons1 = sorted(personList, key=attrgetter('height'))
for person in sortedPerons1:
person.showMysef()
输出的结果和上面是一模一样的,这里不再赘述。
能提出这个问题,说明你一定是带着思考在阅读!之所以还要这么写,出于以下几个原因:
class CompareByHeightAndWeight(ICompare):
"根据身高和体重的综合情况来排序(身高和体重的权重分别是0.6和0.4)"
def comparable(self, person1, person2):
value1 = person1.height * 0.6 + person1.weight * 0.4
value2 = person2.height * 0.6 + person2.weight * 0.4
return value1 - value2
使用策略模式能让我们写的算法适用于各种规则和各种对象类型,极大地提高了算法的灵活性和拓展性。
Get到技能点了吗?