当前情况:
在Java系统中,我们有一个名为Passenger的类,如下,
public Class Passenger{
//lots of member fields
private String firstName ;
private String lastName ;
private WhatEverAttribute att;
//lots of getters & setters
WhatEverAttribute getAtt(){ return att;}
void setAtt(WhatEverAttribute attIn){ this.att=attIn;}
...
//and lots of methods,for example
List<String> doWhatEverFuction(...){ return ... }
...
}
在其他地方的应用程序中,有很多地方可以创建并使用此类:
Passenger p1 = new Passenger();
p.setFirstName("blablabla")
p.setAtt(xxx);
Passenger p2 = new Passenger();
p2.setAtt(yyy)
List retl = p2.doWhatEverFuction(...);
...
该系统以前只管理航空/飞行乘客,因此该乘客 类实际上是航空旅客的数据模型,
现在的问题是,我们需要扩展模型并建立层次结构,因为“乘客”将是具有通用字段和功能的通用“乘客”模型,新模型AirPassenger和SeaPassenger将对其进行扩展: enter image description here
因此将保留一些常见的字段和功能 可以在AirPassenger和SeaPassenger之间共享,但是大多数特定于航空乘客的领域和功能将被下推到AirPassenger,
那么每个人都知道我必须更改从
访问“乘客”的现有代码 Passenger p = new Passenger();
p.xxxxxx();
到
AirPassenger p = new AirPassenger();
p.xxxxxx();
有很多地方,我不想在现有代码中从很多地方手动更改它们,从而可以从整个应用程序访问“乘客”,
我想要的是完成层次结构后,其余代码仍可以正常工作,而无需进行任何更改,通过使用一些技巧,我可以返回 通过新的Passenger()构造函数创建一个AirPassenger,例如:
Passenger{
Passenger(){
return Passenger("Air")
}
Passenger(String type){
Switch(type){
...
case "Air": return new AirPassenger();
...
}
}
}
通过Java,CGLIB或某些其他动态功能,有可能吗?
答案 0 :(得分:1)
最终选择的方法将取决于许多因素,很大程度上取决于代码的使用方式和位置。如果您可以访问此类的所有用法,我强烈建议您提出的解决方案不建议使用-适当的继承层次结构将有助于使代码井井有条,并有可能在将来轻松扩展程序。许多IDE(例如IntelliJ)都提供出色功能,用于智能重构代码并将其提取到新类中,这些功能将自动完成几乎所有工作并确保代码按预期运行。
如果可能,您的情况是使用抽象父类的经典案例。由于没有“一般旅客”之类的东西,因此针对您的层次结构更正确的设计是将“旅客”声明为抽象类。这样,无法直接创建Passenger实例,但是类本身可以保存实现,这些继承类可以根据需要使用或重写。 您还可以向此类添加工厂方法,根据输入(如您建议的那样),该方法将返回正确类型的新Passenger。
编辑:
多态性和类层次结构以非常特殊的方式在Java中工作。也就是说,程序员在维护代码可读性和模块化方面受到一些限制。 您要求的内容(在澄清的注释中)是您无法描述的。
您将创建两个新类:
class AirPassenger extends Passenger {
...
public void doSomethingAir() {
...
}
...
}
class SeaPassenger extends Passenger {
...
public void doSomethingSea() {
...
}
...
}
您可以将其某些方法重构为新的AirPassenger类,然后将其保留在原处。 您会注意到的第一件事是,您不能使用现有的Passenger构造函数来返回AirPassenger或SeaPassenger的实例,因为构造函数是 void方法,没有返回值。因此,您将需要提供一些构造工厂方法来创建AirPassenger或SeaPassenger的实例。
Passenger createPassenger(String passengerType) {
switch (passengerType) {
case "sea":
return new SeaPassenger();
default:
return new AirPassenger();
}
}
您将方法从“乘客”重构为“ AirPassenger”。这些方法在“乘客”类中不再存在,并且不能由“乘客”对象调用。 您可以,但是可以使用显式类型转换将所有乘客对象重新投射到AirPassenger,然后您将能够使用AirPassenger中现在使用的所有方法。 也可以使用一种方法来完成此操作:
AirPassenger convertToAirPassenger(Passenger passenger) {
return (AirPassenger) passenger;
}
答案 1 :(得分:0)
我当然可以找到并替换,大多数IDE都可以做到, 但是问题是系统中有一些配置文件和txt文件,可以用作字典和模板,您知道,它们使用乘客词或添加前缀和后缀,或者小写,您知道,您不能只是查找和替换,因此不仅需要对Java代码进行更改,所以我宁愿在有办法的情况下也不要更改它们,这是我的问题。
//you create an instance of class
ClassA obj = new ClassA();
//you call method doIT() inside ClassA
obj.doIt();
现在,当ClassA成为超类时,我必须对其进行重新建模,然后将这些方法压入其子类,比如说ClassB,所以 ClassB扩展了ClassA,方法doIt()在内部 现在是ClassB , 众所周知,我需要将上面的代码更改为
//you create an instance of ClassB,
ClassB obj = new ClassB();
//or ClassB obj = new ClassA(); you have little code in the ClassA constuctor, etc.
//then you call a method
obj.doIt();
我知道,但是我的问题是,无需对其进行更改
ClassA obj = new ClassA();
obj.doIt();
有什么技巧可以使其与新模型兼容?