3 回答
TA贡献1856条经验 获得超5个赞
您可以实现Visitor模式。
详细答案
这个想法是使用多态来执行类型检查。每个子类都覆盖该accept(Visitor)方法,该方法应在超类中声明。当我们遇到如下情况时:
void add(Vehicle vehicle) {
//what type is vehicle??
}
我们可以将一个对象传递到中声明的方法中Vehicle。如果vehicle类型为Car,并class Car覆盖我们将对象传递给的方法,则该对象现在将在Car类中声明的方法内进行处理。我们利用它的优势:创建一个Visitor对象并将其传递给重写的方法:
abstract class Vehicle {
public abstract void accept(AddToListVisitor visitor);
}
class Car extends Vehicle {
public void accept(AddToListVisitor visitor) {
//gets handled in this class
}
}
这Visitor应该准备好访问类型Car。您想要避免使用的任何类型instanceof都必须在中指定Visitor。
class AddToListVisitor {
public void visit(Car car) {
//now we know the type! do something...
}
public void visit(Plane plane) {
//now we know the type! do something...
}
}
这是类型检查的地方!
当Car接收到访问者时,它应该使用this关键字传递自己。由于我们在class中Car,因此visit(Car)将调用该方法。现在,我们知道了对象的类型,就可以在访问者内部执行所需的操作。
因此,从顶部开始:
您创建一个Visitor,执行所需的操作。访问者应该visit为要对其执行操作的每种对象类型提供一个方法。在这种情况下,我们正在为车辆创建访客:
interface VehicleVisitor {
void visit(Car car);
void visit(Plane plane);
void visit(Boat boat);
}
我们要执行的动作是将车辆添加到某物上。我们将创建一个AddTransportVisitor;负责管理交通运输的访客:
class AddTransportVisitor implements VehicleVisitor {
public void visit(Car car) {
//add to car list
}
public void visit(Plane plane) {
//add to plane list
}
public void visit(Boat boat) {
//add to boat list
}
}
每辆车都应该能够接待来访者:
abstract class Vehicle {
public abstract void accept(VehicleVisitor visitor);
}
当访客被送往车辆时,车辆应调用其visit方法,并将自身传递给参数:
class Car extends Vehicle {
public void accept(VehicleVisitor visitor) {
visitor.visit(this);
}
}
class Boat extends Vehicle {
public void accept(VehicleVisitor visitor) {
visitor.visit(this);
}
}
class Plane extends Vehicle {
public void accept(VehicleVisitor visitor) {
visitor.visit(this);
}
}
这就是类型检查的地方。visit调用了正确的方法,该方法包含根据方法的参数执行的正确代码。
最后一个问题是VehicleVisitor与列表进行交互。这就是您的VehicleManager来历:它封装了列表,使您可以通过一种VehicleManager#add(Vehicle)方法添加载具。
创建访问者时,我们可以将管理器传递给它(可能通过它的构造函数),这样,既然我们知道对象的类型,就可以执行所需的操作。本VehicleManager应包含的游客和拦截VehicleManager#add(Vehicle)来电:
class VehicleManager {
private List<Car> carList = new ArrayList<>();
private List<Boat> boatList = new ArrayList<>();
private List<Plane> planeList = new ArrayList<>();
private AddTransportVisitor addVisitor = new AddTransportVisitor(this);
public void add(Vehicle vehicle) {
vehicle.accept(addVisitor);
}
public List<Car> getCarList() {
return carList;
}
public List<Boat> getBoatList() {
return boatList;
}
public List<Plane> getPlaneList() {
return planeList;
}
}
现在,我们可以为这些AddTransportVisitor#visit方法编写实现:
class AddTransportVisitor implements VehicleVisitor {
private VehicleManager manager;
public AddTransportVisitor(VehicleManager manager) {
this.manager = manager;
}
public void visit(Car car) {
manager.getCarList().add(car);
}
public void visit(Plane plane) {
manager.getPlaneList().add(plane);
}
public void visit(Boat boat) {
manager.getBoatList().add(boat);
}
}
我强烈建议删除add每种车辆的吸气剂方法并声明重载方法。这样可以减少不需要时的“访问”开销,例如manager.add(new Car()):
class VehicleManager {
private List<Car> carList = new ArrayList<>();
private List<Boat> boatList = new ArrayList<>();
private List<Plane> planeList = new ArrayList<>();
private AddTransportVisitor addVisitor = new AddTransportVisitor(this);
public void add(Vehicle vehicle) {
vehicle.accept(addVisitor);
}
public void add(Car car) {
carList.add(car);
}
public void add(Boat boat) {
boatList.add(boat);
}
public void add(Plane plane) {
planeList.add(plane);
}
public void printAllVehicles() {
//loop through vehicles, print
}
}
class AddTransportVisitor implements VehicleVisitor {
private VehicleManager manager;
public AddTransportVisitor(VehicleManager manager) {
this.manager = manager;
}
public void visit(Car car) {
manager.add(car);
}
public void visit(Plane plane) {
manager.add(plane);
}
public void visit(Boat boat) {
manager.add(boat);
}
}
public class Main {
public static void main(String[] args) {
Vehicle[] vehicles = {
new Plane(),
new Car(),
new Car(),
new Car(),
new Boat(),
new Boat()
};
VehicleManager manager = new VehicleManager();
for(Vehicle vehicle : vehicles) {
manager.add(vehicle);
}
manager.printAllVehicles();
}
}
TA贡献2012条经验 获得超12个赞
首先,我对汽车,船只和飞机的清单不太满意。您有多个现实的例子,但清单并非一帆风顺,当您的工厂开始生产潜艇或火箭时会发生什么?
取而代之的是汽车,轮船和飞机类型的枚举。您有一系列的车辆清单。
通用车辆具有抽象属性CatalogAs,各种车辆实际上都实现了该属性并返回适当的值。
添加回答
举报