就oop
来说,必然逃不过两个概念:继承与组合。
什么时候使用继承,使用时候组合?
- 在写简单的代码的时候,谁都清楚该怎么区分。
- 但是,一旦业务逻辑复杂,就很难确定当前情况该使用继承还是组合了。相信使用过任意
oop
语言做过实际项目的人都对此深有体会。 就我个人而言,也是经常在业务代码中,很难去判断当前情况该使用哪一种方式。之前我的一位老师说过,代码没有对错,只有好坏。所以,该如何使用,有时候真的只能用一句:“看具体使用场景”来回答了。
这里给出《Learning Python》中的一个使用继承的范式,及一个使用组合的范式。
首先是继承的范式:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @name : inherit.py
# @author : cat
# @date : 2017/6/25.
from tools import AttrDisplay
# 继承关系
class Employee(AttrDisplay):
def __init__(self, name, salary=0):
self.name = name
self.salary = salary
def giveRaise(self, percent):
self.salary = self.salary + self.salary * percent
def work(self):
return "{} does stuff.".format(self.name)
class Chef(Employee):
def __init__(self, name, ):
Employee.__init__(self, name, 5000)
def work(self):
return "{} make food.".format(self.name)
class Server(Employee):
def __init__(self, name):
Employee.__init__(self, name=name, salary=4000)
def work(self):
return "{} interfaces with customer.".format(self.name)
class PizzaRobot(Chef):
def __init__(self, name):
Chef.__init__(self, name)
def work(self):
return "{} make pizza.".format(self.name)
if __name__ == '__main__':
e = Employee('tom ding')
c = Chef('victor')
s = Server('Ann')
r = PizzaRobot('stone')
print(e, c, s, r, sep="\n")
pass
- 其次是一个组合的范式:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @name : combination.py
# @author : cat
# @date : 2017/6/25.
# 组合关系
from tools import AttrDisplay
from inherit import Server, PizzaRobot
class Customer(AttrDisplay):
def __init__(self, name):
self.name = name
def order(self, server):
print(self.name, "order from", server)
def pay(self, server):
print(self.name, "pay item to", server)
class Oven(AttrDisplay):
def bake(self):
return "oven bake."
class PizzaShop(AttrDisplay):
def __init__(self):
self.chep = PizzaRobot('bob')
self.server = Server('pat')
self.oven = Oven()
def order(self, name):
customer = Customer(name)
customer.order(self.server)
self.server.work()
self.chep.work()
self.oven.bake()
customer.pay(self.server)
if __name__ == '__main__':
shop = PizzaShop()
shop.order("tom ding")
print(".....")
shop.order("pythonCat")
使用的一个工具类:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @name : tools.py
# @author : cat
# @date : 2017/6/25.
class AttrDisplay:
def __gatherAttrs(self):
return ["{}={}".format(key, getattr(self, key))
for key in self.__dict__.keys()]
def __repr__(self):
return "<{}:{}>" \
.format(self.__class__.__name__,
",".join(self.__gatherAttrs()))
def __str__(self):
return AttrDisplay.__repr__(self)
if __name__ == '__main__':
class P(AttrDisplay):
def __init__(self, name, age):
self.name = name
self.age = age
def func(self):
return "func ...."
c = P('tom ding', 32)
print(c)
上述代码清晰易懂:
- 在继承的范式中,给出的是一个员工的继承关系。厨师,服务员都是员工的子类,披萨机器人是厨师的子类。
- 在组合的范式中,披萨店是一个组合类,也是控制器。披萨店里面有烤箱,服务员,厨师,和顾客。其中,除了顾客之外,其他的店里必须存在的,而顾客是流动的,不固定的。
以上的关于oop
的继承与组合的范式只是辅助与警醒如何去正确的使用继承与组合。
在实际项目中,复杂的业务逻辑里面,可能会掺杂各种耦合,导致继承不像继承,组合不像组合。