Java 模式创建具有依赖约束的多态对象
首先,我的结构: 抽象对象Java 模式创建具有依赖约束的多态对象,java,Java,首先,我的结构: 抽象对象 --ObjectA --反对意见 AbstractOtherObject --其他对象a --其他对象b 使用多态性,我想基于我的AbstractObject创建一个AbstractOtherObject。更准确地说,我想要一个OtherObjectA,如果它是ObjectA,B也是一样。 重要的一点是,我不希望依赖于AbstractObject中的AbstractOtherObject。我无法在AbstractObject中创建抽象方法AbstractOtherOb
--ObjectA
--反对意见 AbstractOtherObject
--其他对象a
--其他对象b 使用多态性,我想基于我的
AbstractObject
创建一个AbstractOtherObject
。更准确地说,我想要一个OtherObjectA
,如果它是ObjectA
,B也是一样。重要的一点是,我不希望依赖于
AbstractObject
中的AbstractOtherObject
。我无法在AbstractObject
中创建抽象方法AbstractOtherObject-toOtherObject()
我找不到不使用instanceof的解决方案
提前谢谢
更新:伪代码
如果我没有依赖约束,我会这样做:
public class Any{
void do(AbstractObject o){
AbstractOtherObject otherO = o.toOtherObject();
doSomething(otherO);
}
}
但因为我不想要依赖,我只能做一些丑陋的事情,比如:
public class Any{
void do(AbstractObject o){
AbstractOtherObject otherO;
if(o instanceof ObjectA){
otherO = new OtherObjectA(o);
} else {
otherO = new OtherObjectB(o);
}
doSomething(otherO);
}
}
这不是一个完美的解决方案,但它比[IMO]使用
instanceof
更好,是的一种变体
创建AbstractOtherObjectFactory
抽象类和具体类:OtherObjectAFactory
,OtherObjectBFactory
填充映射
:将扩展AbstractOtherObject
的所有可能类映射到它们的相关工厂
当需要创建新对象时,使用:map.get(obj.getClass()).build(obj)代码>
请注意,AbstractObject
及其派生类不依赖于任何AbstractOtherObject
及其派生类,您消除了instanceof
的使用,但代价是使用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 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());
(*)请注意,如果您确实需要A
功能,您仍然需要加入public OtherA(AbstractObj obj)
。您可以使用访问修饰符确保只能使用其工厂创建otherA
(*)此解决方案并不完美,但应该可以工作。一个更好的解决方案显然是创建一个createOtherObj()
方法,正如您所提到的-但是它需要依赖于AbstractotherObject
访问者模式来拯救
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 {
}
如果无法向具体类添加任何内容,则需要将它们包装在类型感知的可访问包装器中
编辑:
要获得转换后的其他对象,有两种可能的解决方案。您可以将访问者设置为statefull(见上文)。或者,如果需要acceptor方法返回值,则可以使用通用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");
}
}
}
Visitor和Visitable现在是通用的:
interface Visitor<T> {
T visit(A a);
T visit(B b);
T visit(Visitable visitable);
}
interface Visitable {
<T> T accept(Visitor<T> v);
}
界面访问者{
T访问(A);
T访问(B);
T访问(可访问);
}
界面可访问{
不接受(访客v);
}
ConvertServiceSitor是抽象的,并且在每种类型的基础上被子类化为具体的访问者:
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();
}
}
抽象类ConverterVisitor实现Visitor{
公众T访问(可访问){
抛出新的IllegalArgumentException(“类型:“+visitable.getClass().getName()+”不受支持”);
}
公众参观(可参观){
回访((可访问)可访问);
}
公众T访问(B可访问){
回访((可访问)可访问);
}
}
类AConverterVisitor扩展了ConverterVisitor{
@凌驾
公众访问(A){
返回新的AOther();
}
}
A和B的accept方法现在的实现方式如下:
A级扩展Abs{
public <T> T accept(Visitor<T> v) {
return v.visit(this);
}
public <T> T accept(Visitor<T> v) {
return v.visit(this);
}
public不接受(访客v){
回访(本);
}
}
B类扩展了Abs{
public <T> T accept(Visitor<T> v) {
return v.visit(this);
}
public <T> T accept(Visitor<T> v) {
return v.visit(this);
}
public不接受(访客v){
回访(本);
}
}
其他类和抽象类将与第一个示例中的相同。一些关于如何使用这些类的伪代码可能会有所帮助。至少我很难理解您真正想要的是什么。如果您不依赖AbstractObject中的AbstractOtherObject,就无法从AbstractObject返回AbstractOtherObject。我觉得这很好,因为您可以在a
和B
包中使用Visitor
界面,以及AOther
和world
包中的ConverterVisitor
。但是,您确实需要取回新的AOther
实例。因此,访问者中的visit方法返回一个AOther
,并且您具有依赖关系。添加了泛型版本,以及如何将转换器实现为状态完整转换器。见编辑,谢谢。我认为statefull转换器应该可以工作,但在我的情况下不能使用泛型转换器,因为我首先不知道我是在a
实例还是B
实例上调用.accept
。我会尽快测试你的第一个解决方案。您使用预先构造的映射来避免ifs语句,并且使用键而不是instanceof。这是更好的,但这是同样有缺陷的概念。也许没有其他解决办法。无论如何,谢谢。@D0m3我同意这个解决方案有它的问题。。但这是我能想到的最好的遵守“不依赖约束”的办法。我等了一会儿看是否还有其他答案,否则我会选择你的。