【问题标题】:Instantiate an extended class or its parent (depending on circumstances)实例化扩展类或其父类(视情况而定)
【发布时间】:2016-02-25 12:25:13
【问题描述】:

假设我在ProjectA 中有一个名为Human 的类。在同一个项目的CreatureBuilder类中实例化。

现在我想在另一个项目中创建一个名为 Cyborg 的新类,即在 ProjectB 中。 ProjectB 在其导入中有 ProjectA,但 ProjectAProjectB 一无所知。

Cyborg extends Human,也必须被ProjectACreatureBuilder实例化(所以,Cyborg位于ProjectB,我从ProjectB调用CreatureBuilder来实例化Cyborg,但是@ 987654338@位于ProjectA,以及我的Human类)。

CreatureBuilderProjectA 实例化时,我需要一个逻辑来创建Human,并在CreatureBuilderProjectB 实例化时创建Cyborg

我认为可以通过在ProjectA 中使用getCreature() 方法创建接口来实现。此方法将在ProjectB 中被覆盖到return new Cyborg,然后传回ProjectA 中的CreatureBuilder。 还有其他建议吗?您认为最好的解决方法是什么?我可以改用反射 API 吗?

干杯!

【问题讨论】:

  • 可能我没听懂,但是为什么不在两个项目中使用两个不同的CreatureBuilder类呢?
  • @FrankPuffer 好吧,“CreatureBuilder”是一个巨大的类,比如 5k 行或更多的代码。它的逻辑将来可能会改变,所以如果我遵循复制粘贴的路线,我将不得不更新这两个实现。
  • 您不必复制/粘贴整个代码,只需将常用的东西放入一个通用的基类中即可。

标签: java oop design-patterns


【解决方案1】:

Java 8

CreatureBuilder 可以通过请求Supplier 将生物的创造委托给调用者。

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,则原理保持不变,只是它有点冗长。

你必须声明和使用你自己的类似供应商的接口

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 我用 Java 7 等效示例更新了我的答案。
  • 这与下面的 Java 7 有何不同,除了冗长之外,您还需要能够通过传入一个类型来创建不同的对象,而不仅仅是 Human、Cyborg。
  • @Spotted 谢谢。顺便说一句,您之前提到了反射。我会避免使用它,但你知道如何通过反射 API 来完成吗?
  • @svasa 区别在于谁有责任实例化新生物。在您的解决方案中,它是工厂。在我的解决方案中,它是调用者。
【解决方案2】:

我认为您正在研究工厂模式。是的,您可以使用项目 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") 来获取人类对象。

【讨论】:

    猜你喜欢
    • 2021-02-19
    • 2013-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-12
    • 2013-05-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多