【发布时间】:2018-11-19 00:42:34
【问题描述】:
我有两个相关的接口,但是我不确定如何分配一些职责(方法)。
假设一个接口是 Truck,另一个是 ParkingLot。
可以有不同的 Truck 实现,例如 DumpTruck、BoxTruck、FireTruck...,以及 ParkingLot 的不同实现,例如 TruckParkingLot、CarParkingLot、MotorcycleParkingLot...
我有一个程序基本上是一个 TruckParkingLot,它包含以下内容:
private Map<String, Truck> trucks = new ConcurentHashMap();
public void registerTruck(String plate, Truck truck) {
// Code to put a new Truck in the ParkingLot
}
public void removeTruck(String plate) {
// Code to remove a Truck from the ParkingLot
}
public Truck getTruckByPlate(String plate) {
// Code to get Truck with key (plate) from the Map trucks
}
然后是 Truck 接口,它有几个实现。每个实现都不同,因为它们有不同的实例变量。
我还想实现另外两种方法:更新和打印。前者更新选中卡车的实例变量;后者打印所选卡车的实例变量。
我的疑问是这些方法应该在 ParkingLot 接口中还是在 Truck 接口中。
一方面我觉得这些方法应该在 ParkingLot 接口中,因此客户端只需访问 TruckParkingLot y 类即可获取所需的所有信息并进行管理。此外,使用反射,您可以轻松管理类的任何实例(包括私有),而无需知道给定对象有多少实例变量或哪些实例变量。
另一方面,通过将这两个方法放在 ParkingLot 接口中,该接口管理的数据不是 TruckParkingLot 内置的,而是来自给定卡车的实例变量,这违反了责任驱动的设计原则 (私有类实例只能在它们所属的类中处理)。另外,如果更新和打印到 ParkingLot 接口,那么 Truck 接口就会变成一个空接口(没有更多的 Truck 方法)。
另一方面,如果我在 Truck 接口中实现这两个方法,那么我将为该接口的每个实现复制代码,因为更新或打印 BoxTruck 和 DumpTruck 的实例变量的方式几乎使用 getter 和 setter 时相同(使用反射时完全一样)
另一种可能的解决方案是为卡车创建一个抽象类并实现更新和打印方法,其余卡车只是继承这个类。 (我还需要为这个抽象类创建一个接口吗?)。
总之,当我第一次写这篇文章时,我想到了这些选项:
A) 带有所有方法的 ParkingLot 接口;没有方法的卡车接口(空)。
interface ParkingLot {
public void registerVehicle(String plate, Vehicle vehicle);
public void removeVehicle(String plate);
public Vehicle getVehicleByPlate(String plate);
public void updateVehicle(Vehicle vehicle);
public void printVehicleData(Vehicle vehicle);
}
public class TruckParkingLot implements ParkingLot {
private Map<String, Truck> trucks = new ConcurentHashMap();
public void registerVehicle(String plate, Vehicle truck) {
// Code to put a new Truck in the ParkingLot
}
public void removeVehicle(String plate) {
// Code to remove a Truck from the ParkingLot
}
public Truck getVehicleByPlate(String plate) {
// Code to get Truck with key (plate) from the Map trucks
}
public Truck updateVehicle(Vehicle truck) {
// Code to update the inst vars of a Truck using reflection
}
public Truck printVehicleData(Vehicle truck) {
// Code to print the inst vars of a Truck using reflection
}
}
interface Truck extends Vehicle {
// Nothing here
}
public class DumpTruck implements Truck {
// Private instance variables
// Constructor
// Setters and getters
}
public class BoxTruck implements Truck {
// Other private instance variables
// Another constructor
// Setters and getters
}
B) 带有方法的 ParkingLot 接口,带有更新和打印方法的卡车接口。
interface ParkingLot {
public void registerVehicle(String plate, Vehicle vehicle);
public void removeVehicle(String plate);
public Vehicle getVehicleByPlate(String plate);
}
public class TruckParkingLot implements ParkingLot {
private Map<String, Truck> trucks = new ConcurentHashMap();
public void registerVehicle(String plate, Vehicle truck) {
// Code to put a new Truck in the ParkingLot
}
public void removeVehicle(String plate) {
// Code to remove a Truck from the ParkingLot
}
public Truck getVehicleByPlate(String plate) {
// Code to get Truck with key (plate) from the Map trucks
}
}
interface Truck extends Vehicle {
public void updateVehicle(Vehicle vehicle);
public void printVehicleData(Vehicle vehicle);
// Both methods should actually be inherited from Vehicle
// interface, but this doesn't affect the point here.
// Technically the Truck methods would still be empty.
}
public class DumpTruck implements Truck {
// Private instance variables
// Constructor
// Setters and getters
public Truck updateVehicle(Vehicle truck) {
// Code to update the inst var using setters and getters
}
public Truck printVehicleData(Vehicle truck) {
// Code to print the inst var using setters and getters
}
}
public class BoxTruck implements Truck {
// Other private instance variables
// Another constructor
// Setters and getters
public Truck updateVehicle(Vehicle truck) {
// Code to update the inst vars using setters and getters
}
public Truck printVehicleData(Vehicle truck) {
// Code to print the inst vars using setters and getters
}
}
C) ParkingLot 接口及其方法,Truck 抽象类。
interface ParkingLot {
public void registerVehicle(String plate, Vehicle vehicle);
public void removeVehicle(String plate);
public Vehicle getVehicleByPlate(String plate);
}
public class TruckParkingLot implements ParkingLot {
private Map<String, Truck> trucks = new ConcurentHashMap();
public void registerVehicle(String plate, Vehicle truck) {
// Code to put a new Truck in the ParkingLot
}
public void removeVehicle(String plate) {
// Code to remove a Truck from the ParkingLot
}
public Truck getVehicleByPlate(String plate) {
// Code to get Truck with key (plate) from the Map trucks
}
}
public abstract class Truck implements Vehicle {
// private common instance variables to all trucks
// Constructor with all common instance variables
// Setters and getters
public Truck updateVehicle(Vehicle truck) {
// Code to update the inst vars using setters and getters
}
public Truck printVehicleData(Vehicle truck) {
// Code to print the inst vars using setters and getters
}
}
public class DumpTruck implements Truck {
// Private unique instance variables to DumpTruck
// Inherit constructor from superclass
// + initialize unique instance variables for this subclass
// Setters and getters for the unique inst vars of this subclass
@override
public Truck updateVehicle(Vehicle truck) {
// inherit code from superclass
// + update the unique instance variables of this subclass
}
@override
public Truck printVehicleData(Vehicle truck) {
// inherit code from superclass
// + print the unique instance variables of this subclass
}
}
public class BoxTruck implements Truck {
// Private unique instance variables to DumpTruck
// Inherit constructor from superclass
// + initialize unique instance variables for this subclass
// Setters and getters for the unique inst vars of this subclass
@override
public Truck updateVehicle(Vehicle truck) {
// inherit code from superclass
// + update the unique instance variables of this subclass
}
@override
public Truck printVehicleData(Vehicle truck) {
// inherit code from superclass
// + print the unique instance variables of this subclass
}
}
就个人而言,我更喜欢将所有方法都放在 ParkingLot 接口中并使用反射(选项 A),将 Truck 接口留空;或为卡车使用抽象类(选项 C)
但是,真的,我什么都不确定。
提前致谢。
【问题讨论】:
标签: java class methods reflection interface