实例化一个扩展类或其父类(根据情况)。

3
假设我在ProjectA中有一个名为Human的类。在同一项目的CreatureBuilder类中实例化它。
现在我想在另一个项目ProjectB中创建一个名为Cyborg的新类。 ProjectB在其导入中拥有ProjectA,但ProjectA对ProjectB一无所知。
Cyborg扩展了Human,并且必须由ProjectA的CreatureBuilder实例化(因此,Cyborg位于ProjectB中,我从ProjectB调用CreatureBuilder来实例化Cyborg,但CreatureBuilder也位于ProjectA中,以及我的Human类)。
当从ProjectA实例化CreatureBuilder时,我需要一个逻辑来创建Human,当从ProjectB实例化CreatureBuilder时,需要创建Cyborg。
我认为可以通过在ProjectA中创建具有getCreature()方法的接口来实现。这个方法将在ProjectB中被重写以返回new Cyborg,然后传回ProjectA的CreatureBuilder。还有其他建议吗?你认为什么是最好的解决方法?我可以使用反射API吗?
干杯!

也许我没理解,但为什么不在这两个项目中使用两个不同的CreatureBuilder类呢? - Frank Puffer
@FrankPuffer 嗯,“CreatureBuilder”是一个庞大的类,有5000行或更多的代码。它的逻辑可能会在未来发生变化,因此如果我按照复制粘贴的路线进行操作,我将不得不更新两个实现。 - Zhiroslav
你不需要复制/粘贴整个代码,只需将常见的内容放入一个公共基类中。 - Frank Puffer
2个回答

5

Java 8

CreatureBuilder 可以通过请求一个供应商,将生物的创建委托给调用者。

public class CreatureBuilder {
    public Creature getCreature(Supplier<Creature> creatureSupplier)
    {
        //do some unknown things
        return creatureSupplier.get();
    }
}

从ProjectA使用

public class ProjectA {
    public static void main(String[] args) {
        Creature A = new CreatureBuilder().getCreature(Human::new);
    }
}

从ProjectB使用

public class ProjectB {
    public static void main(String[] args) {
        Creature B = new CreatureBuilder().getCreature(Cyborg::new);
    }
}

如果没有被迫使用,不要使用反射。

Java 7

如果你使用Java 7,原则仍然相同,只是稍微冗长一些。

你需要声明并使用自己的类似Supplier的接口。

public interface CreatureSupplier {
    Creature get();
}

public class CreatureBuilder {
    public Creature getCreature(CreatureSupplier creatureSupplier)
    {
        //do some things
        return creatureSupplier.get();
    }
}

使用方法有点冗长

public class ProjectA {
    public static void main(String[] args) {
        Creature A = new CreatureBuilder().getCreature(new CreatureSupplier() {
            @Override
            public Creature get() {
                return new Human();
            }
        });
    }
}

public class ProjectB {
    public static void main(String[] args) {
        Creature B = new CreatureBuilder().getCreature(new CreatureSupplier() {
            @Override
            public Creature get() {
                return new Cyborg();
            }
        });
    }
}

好的,这就是它,您已经获得了与Java 8相同的行为。


谢谢!很棒的例子,可能是2016年可用的最佳解决方案。但不幸的是,我无法升级当前项目的平台到Java 8...现在必须坚持使用与1.7兼容的解决方案。 - Zhiroslav
@Zhiroslav,我更新了我的答案,并提供了一个Java 7的等效示例。 - Spotted
1
除了冗长之外,这与Java 7下面的有何不同,您还需要能够通过传递类型而不仅仅是Human、Cyborg来创建不同的对象。 - SomeDude
@Spotted 谢谢。顺便说一下,你之前提到了反射。我会避免使用它,但你知道如何通过反射API来实现吗? - Zhiroslav
1
@svasa,区别在于谁有责任实例化新的对象。在你的解决方案中,是工厂;而在我的解决方案中,是调用者。 - Spotted
显示剩余3条评论

1
我觉得你正在考虑工厂模式。是的,你可以在项目A中使用接口和工厂类,在项目B中扩展它。

例如:

在项目A中:

public interface CreatureBuilder
{
   Creature getCreature(String type);
}

public class Creature
{
   //fields of Creature class
}

public class Human extends Creature
{
  //fields of Human
}

public class Ape extends Creature
{
  //fields of Ape
}



public class ProjectAFactory implements CreatureBuilder
{
   @Override
   public Creature getCreature( String type )
   {
      switch(type)
      {
         case("Human"): return new Human();
         case("Ape") : return new Ape();
         default : return null;
      }
   }
}

你可以调用ProjectAFactory.getCreature("Human");来创建一个Human对象。
然后在项目B中:
public class ProjectBFactory extends ProjectAFactory
{
    @Override
    public Creature getCreature(String type)
    {
       switch(type)
       {
          case ( "Cyborg" ) : return new Cyborg();
          default : return super.getCreature(type);
       }
    }

}


public class Cyborg extends Creature
{
   //fields related to Cyborg which also fields of Creature in project A
}

你可以调用ProjectBFactory.getCreature("Cyborg");来创建Cyborg对象,或者使用ProjectBFactory.getCreature("Human")获取一个Human对象。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接