使用 class 组合 (Python) 实现简单的 OOP 设计
Implementation of simple OOP design with class composition (Python)
我正在研究设计模式和最佳实践,尤其是class组合()。我有一个具体的例子,我发现很难实现一个好的OOP设计。
简单(?)示例:
假设有一个车库的概念,里面有汽车,并且有一个对外部服务的调用,该服务的响应提供了车库中每辆汽车的信息。
这是我想要捕获并创建 classes 的示例响应:
[{'carID': '1x148i-36y5-5rt2',
'carDimensions': {'top': 275,
'left': 279,
'width': 75,
'height': 75},
'carAttributes': {'weight': {'weightLevel': 'medium',
'value': 1.6},
'topSpeed': {'sppedLevel': 'good',
'value': 0.7},
'noise': {'noiseLevel': 'low',
'value': 0.32},
'accessories': [{'optionsLevel': 'poor',
'quality': 2.8}]}},
{'carID': '223a3-33e5-4ea3',
'carDimensions': {'top': 241,
'left': 234,
'width': 71,
'height': 65},
'carAttributes': {'weight': {'weightLevel': 'light',
'value': 1.1},
'topSpeed': {'sppedLevel': 'great',
'value': 1.6},
'noise': {'noiseLevel': 'high',
'value': 0.97},
'accessories': [{'optionsLevel': 'great',
'quality': 3.2}]}}]
以下是我的 class 设计方法。
我尝试创建一个 Car
class 来提取每个字段,如下所示:
class `Car`:
def __init__(self, car_response_dictionary):
self.car = car_response_dictionary
def get_carID(self):
return self.car.get("carID")
# etc.
和另一个 class 来处理一些基于 carDimensions
:
的计算
class Size:
def __init__(self, top, left, width, height):
self.top = top
self.left = left
self.width = width
self.height = height
def get_coordinates(self):
bottom = self.left + self.height
right = self.top + self.width
return (self.left, self.top), (bottom, right)
和一个 class 来捕捉包含 Car
对象列表的车库的概念:
class Garage:
def __init__(self, datestamp, cars):
self.datestamp = datestamp
self.cars = cars
# do stuff based on cars
所以,我的想法是创建一个 Garage
的实例并在 cars
中获取响应列表,我尝试通过迭代将每辆车解包为 Car
实例对象通过 cars
字典列表和 - 使用 class 组合 - 为每辆车创建一个 Car
实例。
在这一点上,我发现无法在 Python 中实现我的设计,我认为可能要归咎于我设计中的方法或者我对 class 构图的理解不足。
如果有人能为上面的例子提供一个简单的代码实现,那将对我很有教育意义。即使这意味着提出了新的设计(例如,我正在考虑制作 Response
class)。
下面是几个 classes 和一个使用组合的 'main'(使用 Size class 作为 Car class 的数据成员)。
#
# Note that the code does not use 'dict' as an argument for the Car __init__
# but it can be easily modified and use dict as input
#
class Car:
def __init__(self, id, weight, top_speed, noise, size):
self.id = id
self.weight = weight
self.top_speed = top_speed
self.noise = noise
self.size = size
def get_id(self):
return self.id
def __str__(self):
return 'id: {} weight: {} top speed: {} noise: {} size: {}'.format(self.id, self.weight, self.top_speed,
self.noise,
self.size)
class Size:
def __init__(self, top, left, width, height):
self.top = top
self.left = left
self.width = width
self.height = height
def get_coordinates(self):
bottom = self.left + self.height
right = self.top + self.width
return (self.left, self.top), (bottom, right)
def __str__(self):
return '[top: {} left: {} width: {} height: {}]'.format(self.top, self.left, self.width, self.height)
class Garage:
def __init__(self):
self.cars_holder = {}
def add_car(self, car):
self.cars_holder[car.get_id()] = car
def remove_car(self, car_id):
del self.cars_holder[car_id]
def show_cars(self):
for car in self.cars_holder.values():
print(car)
GARAGE_AS_DICT = [{'id': '1x148i-36y5-5rt2',
'dimensions': {'top': 275,
'left': 279,
'width': 75,
'height': 75},
'attrs': {'weight': 12,
'top_speed': 0.7,
'noise': 0.45
}},
{'id': '223a3-33e5-4ea3',
'dimensions': {'top': 241,
'left': 234,
'width': 71,
'height': 65},
'attrs': {'weight': 12,
'top_speed': 0.74,
'noise': 0.4345
}
}]
if __name__ == "__main__":
garage = Garage()
for dict_car in GARAGE_AS_DICT:
attrs = dict_car['attrs']
dimensions = dict_car['dimensions']
garage.add_car(Car(dict_car['id'], attrs['weight'], attrs['top_speed'], attrs['noise'],
Size(dimensions['top'], dimensions['left'], dimensions['width'], dimensions['height'])))
garage.show_cars()
输出:
id: 223a3-33e5-4ea3 weight: 12 top speed: 0.74 noise: 0.4345 size: [top: 241 left: 234 width: 71 height: 65]
id: 1x148i-36y5-5rt2 weight: 12 top speed: 0.7 noise: 0.45 size: [top: 275 left: 279 width: 75 height: 75]
我正在研究设计模式和最佳实践,尤其是class组合(
简单(?)示例:
假设有一个车库的概念,里面有汽车,并且有一个对外部服务的调用,该服务的响应提供了车库中每辆汽车的信息。
这是我想要捕获并创建 classes 的示例响应:
[{'carID': '1x148i-36y5-5rt2',
'carDimensions': {'top': 275,
'left': 279,
'width': 75,
'height': 75},
'carAttributes': {'weight': {'weightLevel': 'medium',
'value': 1.6},
'topSpeed': {'sppedLevel': 'good',
'value': 0.7},
'noise': {'noiseLevel': 'low',
'value': 0.32},
'accessories': [{'optionsLevel': 'poor',
'quality': 2.8}]}},
{'carID': '223a3-33e5-4ea3',
'carDimensions': {'top': 241,
'left': 234,
'width': 71,
'height': 65},
'carAttributes': {'weight': {'weightLevel': 'light',
'value': 1.1},
'topSpeed': {'sppedLevel': 'great',
'value': 1.6},
'noise': {'noiseLevel': 'high',
'value': 0.97},
'accessories': [{'optionsLevel': 'great',
'quality': 3.2}]}}]
以下是我的 class 设计方法。
我尝试创建一个 Car
class 来提取每个字段,如下所示:
class `Car`:
def __init__(self, car_response_dictionary):
self.car = car_response_dictionary
def get_carID(self):
return self.car.get("carID")
# etc.
和另一个 class 来处理一些基于 carDimensions
:
class Size:
def __init__(self, top, left, width, height):
self.top = top
self.left = left
self.width = width
self.height = height
def get_coordinates(self):
bottom = self.left + self.height
right = self.top + self.width
return (self.left, self.top), (bottom, right)
和一个 class 来捕捉包含 Car
对象列表的车库的概念:
class Garage:
def __init__(self, datestamp, cars):
self.datestamp = datestamp
self.cars = cars
# do stuff based on cars
所以,我的想法是创建一个 Garage
的实例并在 cars
中获取响应列表,我尝试通过迭代将每辆车解包为 Car
实例对象通过 cars
字典列表和 - 使用 class 组合 - 为每辆车创建一个 Car
实例。
在这一点上,我发现无法在 Python 中实现我的设计,我认为可能要归咎于我设计中的方法或者我对 class 构图的理解不足。
如果有人能为上面的例子提供一个简单的代码实现,那将对我很有教育意义。即使这意味着提出了新的设计(例如,我正在考虑制作 Response
class)。
下面是几个 classes 和一个使用组合的 'main'(使用 Size class 作为 Car class 的数据成员)。
#
# Note that the code does not use 'dict' as an argument for the Car __init__
# but it can be easily modified and use dict as input
#
class Car:
def __init__(self, id, weight, top_speed, noise, size):
self.id = id
self.weight = weight
self.top_speed = top_speed
self.noise = noise
self.size = size
def get_id(self):
return self.id
def __str__(self):
return 'id: {} weight: {} top speed: {} noise: {} size: {}'.format(self.id, self.weight, self.top_speed,
self.noise,
self.size)
class Size:
def __init__(self, top, left, width, height):
self.top = top
self.left = left
self.width = width
self.height = height
def get_coordinates(self):
bottom = self.left + self.height
right = self.top + self.width
return (self.left, self.top), (bottom, right)
def __str__(self):
return '[top: {} left: {} width: {} height: {}]'.format(self.top, self.left, self.width, self.height)
class Garage:
def __init__(self):
self.cars_holder = {}
def add_car(self, car):
self.cars_holder[car.get_id()] = car
def remove_car(self, car_id):
del self.cars_holder[car_id]
def show_cars(self):
for car in self.cars_holder.values():
print(car)
GARAGE_AS_DICT = [{'id': '1x148i-36y5-5rt2',
'dimensions': {'top': 275,
'left': 279,
'width': 75,
'height': 75},
'attrs': {'weight': 12,
'top_speed': 0.7,
'noise': 0.45
}},
{'id': '223a3-33e5-4ea3',
'dimensions': {'top': 241,
'left': 234,
'width': 71,
'height': 65},
'attrs': {'weight': 12,
'top_speed': 0.74,
'noise': 0.4345
}
}]
if __name__ == "__main__":
garage = Garage()
for dict_car in GARAGE_AS_DICT:
attrs = dict_car['attrs']
dimensions = dict_car['dimensions']
garage.add_car(Car(dict_car['id'], attrs['weight'], attrs['top_speed'], attrs['noise'],
Size(dimensions['top'], dimensions['left'], dimensions['width'], dimensions['height'])))
garage.show_cars()
输出:
id: 223a3-33e5-4ea3 weight: 12 top speed: 0.74 noise: 0.4345 size: [top: 241 left: 234 width: 71 height: 65]
id: 1x148i-36y5-5rt2 weight: 12 top speed: 0.7 noise: 0.45 size: [top: 275 left: 279 width: 75 height: 75]