Создайте определенный класс в графе объектов с помощью Guice

Я застрял в ситуации, когда рано решил не создавать конкретный график с помощью Guice. Мне нужен завод, но я не могу понять, как его построить.

Чего я достиг, так это системы управления игровыми объектами с учетом сессий.

Все объекты, которые должны быть вовлечены в эту работу, работают нормально.

Все они созданы с помощью инъекций, провайдеров, фабрики и т.д.

Единственный объект, которым мне действительно нужно уметь управлять на этом уровне, это Предметы.

Предметы - также единственный объект, который я не создаю.

Элементы также имеют сложную иерархию классов, которую клиент знает заранее, а код платформы - нет. В своем первоначальном проекте я построил свою собственную фабрику, чтобы иметь возможность использовать мои компоненты для правильной сборки этих объектов.

До сих пор это работало нормально, так как эти объекты должны участвовать в уровне управления, мне нужно найти хитрое решение.

Вот текущая реализация:

abstract class Item{
  public Item(ItemID item){
    ...
  }
  ...
}

class MyItem extends Item{
   ...
}

class MyOtherItem extends MyItem{
   ...
}

class MyFavoriteItem extends Item{
   ...
}

Моя текущая не хитрая реализация выглядит примерно так

class ItemFactory{
   //this sequence generator is plugged into my persistance layer. Allows for generating
   //restful api calls for a specific item.
   @Inject
   private SequenceGenerator sequenceGenerator;

   public ItemID getNextItemID(){
     return sequenceGenerator.generateNextItemID();
   }

   //NOTE: these created objects do not participate in AOP
   //since they are not created by guice
   public <I extends Item> I createItem(Class<I> type){
     Item myItem = type.getConstructor(ItemID.class).newInstance(getNextItemID());
     return (I)myItem;
   }
}

Подтипы мне совершенно неизвестны и обычно предоставляются клиентским модулем. У меня есть несколько аннотаций о том, что с любыми созданными объектами я могу обеспечить управляемое состояние в разрабатываемой игровой среде.

Он прекрасно работает для всех объектов, кроме элемента..., так как они не являются искусными объектами.

Я бы предпочел что-то вроде этого:

class MyItem extends Item{
  @Inject
  public MyItem(@Assisted ItemID itemID);
}

interface MyGuiceFactory{
  public <I extends Item> I createItem(Class<I> type, ItemID itemID);
}

class MyGuiceModule extends AbstractModule{
  public void configure(){
    install(new FactoryModuleBuilder().build(MyGuiceFactory.class));
  }
}

class MyGuiceApp{
  @Inject
  private MyGuiceFactory factory;

  private SequenceGenerator sequenceGenerator

  @Inject
  public MyGuiceApp(SequenceGenerator generator){
    sequenceGenerator = generator;
  }

  public ItemID getNextItemID(){
    return sequenceGenerator.generateNextSequenceID(ItemID.class);
  }

  public <I extends Item> I createItem(Class<I> type){
    return (I)factory.createItem(type, getNextItemID());
  }
}

Поскольку Guice не может использовать общий статический тип в качестве ключа, он не знает, что строить. Так как я не могу связать это с чем-то конкретным или попросить, чтобы это было связано с чем-то конкретным

Я застрял не в состоянии построить это с хитростью. Однако у меня есть некоторый код AOP, который должен быть создан guice.

Если я могу создавать подтипы из своего приложения, эти подтипы могут участвовать в моем уровне состояния управляемой игры.

Любой совет будет большой помощью.

Любая рекомендация по поводу перефразирования вопроса также будет принята с благодарностью.

1 ответ

Решение

Как видите, ваша игра сама является доморощенным ioc-контейнером. Как я понимаю, где-то у вас есть

class AClass
{
  @Inject private Game game;
  void method() {
    Weapon weapon = game.createItem(AK47.class);
    weapon.shoot();
  }
}

что я имею в виду под использованием провайдера:

class AClass
{ 
  @Inject private Provider<AK47> ak47Provider;
  void method() {
    Weapon weapon = ak47Provider.get();
    weapon.shoot();
  }
}

Когда вам просто нужно настроить модули инжектора для привязки всех провайдеров, которые вы можете иметь в приложении.

Тот же эффект, что вы могли бы сделать, если вы вводите Injector в игру и использовать его как фабрику объектов:

class GameBase
{
  @Inject private Injector injector;
  public <I extends Item> I createItem(Class<I> itemType){
    return injector.getInstance(itemType);
  }
}

Вы видите это? com.google.inject.Injector#getInstance имеет точно такую ​​же подпись, как ваша createItem?

Но я предпочитаю первый вариант, он выглядит чище и уменьшает зависимости.

Другие вопросы по тегам