用程序模拟生活

随着社会的发展,时代的进步,出行的方式很多,地铁、快速公交、滴滴打车、共享单车等等,采用什么样的方式出行并不重要,重要的选择那种出现方式能准时到达目的地。

代码:

  1. from abc import ABCMeta, abstractmethod
  2. class IVehicle(metaclass=ABCMeta):
  3. """交通工具的抽象类"""
  4. @abstractmethod
  5. def running(self):
  6. pass
  7. class SharedBicycle(IVehicle):
  8. """共享单车"""
  9. def running(self):
  10. print("骑共享单车(轻快便捷)", end="")
  11. class ExpressBus(IVehicle):
  12. """快速公交车"""
  13. def running(self):
  14. print("坐快速公交车(绿色环保)", end="")
  15. class Express(IVehicle):
  16. """快车"""
  17. def running(self):
  18. print("打快车(快速便捷)", end="")
  19. class Subway(IVehicle):
  20. """地铁"""
  21. def running(self):
  22. print("坐地铁(安全高效)", end="")
  23. class Classmate:
  24. """来聚餐的同学"""
  25. def __init__(self, name, vechicle):
  26. self.__name = name
  27. self.__vechicle = vechicle
  28. def attend_the_dinner(self):
  29. print(self.__name + " ", end="")
  30. self.__vechicle.running()
  31. print(" 来聚餐! ")
  32. def test_the_dinner():
  33. shared_bicycle = SharedBicycle()
  34. joe = Classmate("Joe", shared_bicycle)
  35. joe.attend_the_dinner()
  36. subway = Subway()
  37. helen = Classmate("Helen", subway)
  38. helen.attend_the_dinner()
  39. express_bus = ExpressBus()
  40. henry = Classmate("Henry", express_bus)
  41. henry.attend_the_dinner()
  42. express = Express()
  43. ruby = Classmate("Ruby", express)
  44. ruby.attend_the_dinner()
  45. if __name__ == '__main__':
  46. test_the_dinner()

什么是策略模式

定义一系列的算法,将每个算法都封装起来,并且使它们之间可以相互替换,策略模式使算法可以独立于使用它的用户变化。

策略模式设计思想

将不同的出行方式理解成一种出行算法,将这些算法抽象出一个基类IVehicle,并定义一系列算法、SharedBicycle 、ExpressBus、Express、Subway。我们可以选择任意种出行方式,并且可以方便地更换出行方式。
策略模式的核心思想是:对算法、规则进行封装,使得替换算法和新增算法更加灵活。

模型说明

策略模式中的主要有三个角色,在设计策略模式时要找到并区分角色。
1.上下文环境:起着承上启下的作用,屏蔽上层应用对策略的直接访问,封装可能存在变化。
2.策略抽象:策略(算法)的抽象类,定义统一的接口,规定每个子集类必须实现算法。
3.具备的策略: 策略的具体实现者,可以有多个不同的实现。

策略模式的优缺点

优点:
1.算法可以自由切换
2.避免使用多重条件判断
3.方便拓展和增加的算法
缺点:
1.所有算法策略的类都对外暴露。

实战

有一个Person类,有年龄(age)、身高(height)、体重(weight)三个属性。现在要对Person类的一组对象进行排序,但并没有确定用什么规则来排序,有时需要根据年龄进行排序,有时需要根据身高排序….

代码

  1. from abc import ABCMeta, abstractmethod
  2. class Person:
  3. """人类"""
  4. def __init__(self, name, age, weight, height):
  5. self.name = name
  6. self.age = age
  7. self.weight = weight
  8. self.height = height
  9. def show_myself(self):
  10. print("%s 年龄: %d 岁, 体重: %0.2fkg, 身高: %0.2fm" % (self.name, self.age, self.weight, self.height))
  11. class ICompare(metaclass=ABCMeta):
  12. """比较算法"""
  13. @abstractmethod
  14. def comparable(self, person1, person2):
  15. "person1 > person2 返回值 大于0, person1 == person2 返回0 person1 < person2 返回小于0"
  16. pass
  17. class ComparableByAge(ICompare):
  18. """通过年龄排序"""
  19. def comparable(self, person1, person2):
  20. return person1.age - person2.age
  21. class ComparaByHeight(ICompare):
  22. """按身高排序"""
  23. def comparable(self, person1, person2):
  24. return person1.height - person2.height
  25. class ComparaByWeight(ICompare):
  26. """按身高排序"""
  27. def comparable(self, person1, person2):
  28. return person1.weight - person2.weight
  29. class SortPerson:
  30. """Person排序类"""
  31. def __init__(self, compare):
  32. self.__compare = compare
  33. def sort(self,person_list):
  34. """排序算法"""
  35. n = len(person_list)
  36. for i in range(0, n-1):
  37. for j in range(0, n-i-1):
  38. if (self.__compare.comparable(person_list[j], person_list[j+1]) > 0):
  39. tmp = person_list[j]
  40. person_list[j] = person_list[j+1]
  41. person_list[j+1] = tmp
  42. j += 1
  43. i += 1
  44. def test_sort_person():
  45. person_list = [
  46. Person("Tony", 2, 54.5, 0.82),
  47. Person("Jack", 31, 74.5, 1.82),
  48. Person("Nick", 54, 44.5, 1.59),
  49. Person("Eric", 23, 62.5, 1.72),
  50. Person("Helen", 16, 45.5, 1.60),
  51. ]
  52. print("根据年龄排序")
  53. age_sort = SortPerson(ComparableByAge())
  54. age_sort.sort(person_list)
  55. for person in person_list:
  56. person.show_myself()
  57. print("根据身高排序")
  58. height_sort = SortPerson(ComparaByHeight())
  59. height_sort.sort(person_list)
  60. for person in person_list:
  61. person.show_myself()
  62. print("根据体重排序")
  63. weight_sort = SortPerson(ComparaByWeight())
  64. weight_sort.sort(person_list)
  65. for person in person_list:
  66. person.show_myself()
  67. if __name__ == '__main__':
  68. test_sort_person()

应用场景

1.如果系统里面有许多类,它们之间的区别仅在于有不同行为,那么可以使用策略模式动态地让一个对象在许多行为中选择一个。
2.一个系统需要动态地在几种算法中选择一种。
3.设计程序接口时希望部分内部实现由调用方自己实现。