首先,我的结构:
AbstractObject
--ObjectA
--ObjectB
AbstractOtherObject
--OtherObjectA
--OtherObjectB
对于多态,我想根据我的AbstractOtherObject
创建AbstractObject
。更确切地说,如果OtherObjectA
是ObjectA
,我需要AbstractOtherObject
重要的是,我不想在AbstractObject
中依赖AbstractOtherObject toOtherObject()
。我无法在AbstractObject
中制作抽象方法public class Any{
void do(AbstractObject o){
AbstractOtherObject otherO = o.toOtherObject();
doSomething(otherO);
}
}
。
我找不到不使用 instanceof 的解决方案。
提前致谢。
更新:伪代码
如果我没有依赖性约束,我会这样做:
public class Any{
void do(AbstractObject o){
AbstractOtherObject otherO;
if(o instanceof ObjectA){
otherO = new OtherObjectA(o);
} else {
otherO = new OtherObjectB(o);
}
doSomething(otherO);
}
}
但是因为我不想要依赖,所以我只能做一些丑陋的事情:
{{1}}
答案 0 :(得分:1)
游客模式救援!
public class VisitorExample {
public static void main(String[] args) {
ConverterVisitor converterVisitor = new ConverterVisitor();
A a = new A();
B b = new B();
a.accept(converterVisitor);
AbsOther aother = converterVisitor.getOther();
b.accept(converterVisitor);
AbsOther bother = converterVisitor.getOther();
}
}
要点是让一个单独的类在这种情况下ConverterVisinor做实际的转换类型之间的工作。
Visitor类需要知道应该访问的不同具体类,但Visitable只需要依赖于Visitor接口。
interface Visitor {
void visit(A a);
void visit(B b);
void visit(Visitable visitable);
}
interface Visitable {
void accept(Visitor v);
}
因此,在类型之间进行转换的实际工作的访问者看起来像:
class ConverterVisitor implements Visitor {
// Added field and getter to store the other object in...
private AbsOther other;
public AbsOther getOther {
return other;
}
public void visit(B b) {
System.out.println("Convert a to BOther");
other = new BOther();
}
public void visit(A a) {
System.out.println("Convert a to AOther");
other = new AOther();
}
@Override
public void visit(Visitable visitable) {
throw new IllegalArgumentException("Type: " +
visitable.getClass().getName() + " not supported");
}
}
然后,转换中涉及的抽象类和类可以如下所示:
abstract class Abs implements Visitable { }
abstract class AbsOther { }
class A extends Abs {
public void accept(Visitor v) {
v.visit(this);
}
}
class B extends Abs {
public void accept(Visitor v) {
v.visit(this);
}
}
class AOther extends AbsOther {
}
class BOther extends AbsOther {
}
如果您无法在具体类中添加任何内容,则需要将它们包装在类型识别的可访问包装器中。
修改强> 要获得转换的其他对象,您有两种可能的解决方案。要么你可以使访问者满意(见上文)。或者,如果您需要使用acceptor方法返回值,则可以使用Generic Visitor / Visitable。
public class VisitorExample {
public static void main(String[] args) {
AConverterVisitor converterVisitor = new AConverterVisitor();
A a = new A();
B b = new B();
AOther aother = a.accept(converterVisitor);
System.out.println("Got AOther!");
try {
b.accept(converterVisitor);
} catch (IllegalArgumentException iae) {
System.out.println("Calling accept on b with a AConverterVisitor will result in a exception");
}
}
}
访客和可访问现在是通用的:
interface Visitor<T> {
T visit(A a);
T visit(B b);
T visit(Visitable visitable);
}
interface Visitable {
<T> T accept(Visitor<T> v);
}
ConverterVisitor是抽象的,并且按类型划分给具体访问者:
abstract class ConverterVisitor<T> implements Visitor<T> {
public T visit(Visitable visitable) {
throw new IllegalArgumentException("Type: " + visitable.getClass().getName() + " not supported");
}
public T visit(A visitable) {
return visit((Visitable) visitable);
}
public T visit(B visitable) {
return visit((Visitable) visitable);
}
}
class AConverterVisitor extends ConverterVisitor<AOther> {
@Override
public AOther visit(A a) {
return new AOther();
}
}
A和B的接受方法现在将实现如下:
A类延伸Abs {
public <T> T accept(Visitor<T> v) {
return v.visit(this);
}
}
B级延伸Abs {
public <T> T accept(Visitor<T> v) {
return v.visit(this);
}
}
其他类和抽象类与第一个示例中的相同。
答案 1 :(得分:0)
不是一个完美的解决方案,但它更好[IMO]然后使用instanceof
,是abstract factory pattern的变体。
创建AbstractOtherObjectFactory
抽象类和具体类:OtherObjectAFactory
,OtherObjectBFactory
。
填充Map<Class,AbstractOtherObjectFactory>
:将所有可能扩展AbstractOtherObject
的类映射到相关工厂。
当需要创建新对象时使用:map.get(obj.getClass()).build(obj);
请注意AbstractObject
及其派生类不依赖于AbstractOtherObject
及其派生类中的任何一个,并且消除了instanceof
的使用 - 但代价是使用{ {1}}。
示例:强>
第一类课程:
getClass()
第二类课程:
public abstract static class AbstractObj {
@Override
public String toString() {
return "AbstractObj";
}
}
public static class A extends AbstractObj {
@Override
public String toString() {
return "A";
}
}
工厂类:
public abstract static class OtherAbstractObj {
@Override
public String toString() {
return "AbstractObj";
}
}
public static class OtherA extends OtherAbstractObj {
public OtherA(AbstractObj obj) { }
@Override
public String toString() {
return "OtherA";
}
}
填充地图[在程序生命周期内只需要执行一次]:
public static interface Factory {
public abstract OtherAbstractObj build(AbstractObj obj);
}
public static class OtherAFactory implements Factory {
@Override
public OtherAbstractObj build(AbstractObj obj) {
return new OtherA(obj);
}
}
从原始对象创建一个新的第二个类型对象:
Map<Class<? extends AbstractObj>,Factory> map = new HashMap<Class<? extends AbstractObj>, Test.Factory>();
map.put(A.class, new OtherAFactory());
(*)请注意,如果您确实需要 AbstractObj a = new A();
OtherAbstractObj other = map.get(a.getClass()).build(a);
System.out.println(other);
功能,则仍需要投射public OtherA(AbstractObj obj)
。您可以使用访问修饰符来确保只能使用其工厂创建A
。
(*)这个解决方案并不完美,但应该可行。如上所述,更好的解决方案显然是创建otherA
方法 - 但它需要依赖于createOtherObj()