Так как вас интересует лучшая практика ООП, вы должны игнорировать снижение производительности, которое вы получаете с опцией 2. Единственное, что вас должно заинтересовать, это сделать любую опцию, излишне увеличивающую связь между двумя классами, нарушена ли инкапсуляция и сохраняется личность.
Учитывая это, вариант 2 менее желателен, так как вы не можете определить, какие другие объекты содержат ссылки на исходный автомобиль или, что еще хуже, содержат автомобиль. Короче говоря, вы нарушаете ограничение идентичности, поскольку два объекта в системе могут иметь разные представления о состоянии автомобиля. Вы рискуете сделать всю систему несовместимой.
Конечно, ваша конкретная среда может этого избежать, но, безусловно, было бы лучше избегать этого.
Последний пункт, имеет ли ваш объект bodyShop состояние; поведение и личность? Я понимаю, что вы объяснили только необходимый минимум, но, возможно, bodyShop на самом деле не является объектом.
Функциональный v OO приближается
Интересно отметить, что вариант 2 будет близок к подходу в среде функционального программирования - поскольку изменения состояния не допускаются, единственным подходом будет создание нового автомобиля, если его цвет изменился. Это не совсем то, что вы предлагаете, но это близко.
Это может звучать как полное излишество, но оно имеет некоторые интересные последствия для доказательства правильности кода и параллелизма.