问题:没有继承
让我们根据问题中的给定代码构建一个示例。不同的车辆以不同的方式进行维修。因此,我们有不同的类Bike
,Car
因为服务 a 的策略与服务 aBike
的策略不同Car
。
该Garage
课程接受各种车辆进行维修。观察代码,看看Garage
类是如何违反开闭原则的:
class Bike {
public void service() {
System.out.println("Bike servicing strategy performed.");
}
}
class Car {
public void service() {
System.out.println("Car servicing strategy performed.");
}
}
class Garage {
public void serviceBike(Bike bike) {
bike.service();
}
public void serviceCar(Car car) {
car.service();
}
}
Truck
正如您可能已经注意到的那样,每当Bus
需要维修一些新车时,Garage
都需要对其进行修改以定义新方法serviceTruck()
和serviceBus()
. 这意味着Garage
班级必须了解所有可能的车辆,例如、Bike
、Car
等。因此,它对修改的开放性违反了开闭原则。此外,它不开放扩展,因为要扩展新功能,我们需要对其进行更改。Bus
Truck
解决方案:继承
抽象
为了解决上述代码中的问题,满足开闭原则,我们需要抽象出每种车辆的服务策略的实现细节。这意味着我们需要对和类进行抽象。Bike
Car
多态性
我们还希望Garage
该类接受多种形式的车辆,例如 等Bus
,Truck
而不仅仅是Bike
和Car
。这意味着我们需要多态性(多种形式)。
遗产
所以,为了满足开闭原则,最重要的机制是抽象和多态。在 Java、C# 等静态类型语言中,提供抽象和多态性的重要工具是继承。
为了抽象出各种类型车辆的服务策略的实现细节,我们使用了一个interface
被调用Vehicle
并拥有一个抽象方法service()
。
对于Garage
接受多种形式的类Vehicle
,我们将其方法的签名更改service(Vehicle vehicle) { }
为接受接口Vehicle
而不是实际的实现等Bike
。Car
我们还从类中删除了多个方法,因为一个方法将接受多种形式。
interface Vehicle {
void service();
}
class Bike implements Vehicle {
@Override
public void service() {
System.out.println("Bike servicing strategy performed.");
}
}
class Car implements Vehicle {
@Override
public void service() {
System.out.println("Car servicing strategy performed.");
}
}
class Garage {
public void service(Vehicle vehicle) {
vehicle.service();
}
}
关闭进行修改
正如您在上面的代码中看到的那样,现在Garage
该类已关闭以进行修改,因为它现在不了解各种类型车辆的服务策略的实现细节,并且可以接受任何类型的 new Vehicle
. 我们只需要从Vehicle
接口扩展新车辆并将其发送到Garage
. 我们不需要更改Garage
类中的任何代码。
另一个对修改关闭的实体是我们的Vehicle
接口。我们不必更改界面来扩展我们软件的功能。
开放扩展
现在,Garage
该类在将支持新类型的上下文中对扩展开放Vehicle
,无需修改。
我们的Vehicle
接口对扩展是开放的,因为要引入任何新的车辆,我们可以从Vehicle
接口扩展并提供一个新的实现以及为该特定车辆提供服务的策略。
所以,正如你所看到的,继承是我们用来遵守开闭原则规则的编程语言提供的一个公正的工具。
就是这样!希望有帮助。