2016-05-14 2 views
0

У меня есть много классов, каждый из которых, реализующие GeneralInterface и, возможно, дополнительные функциональные интерфейсы:Есть ли способ унифицировать методы, включающие только функциональные интерфейсы в один?

interface GeneralInterface {} 

class MyObjectTypeOne implements GeneralInterface { /*...*/} 

class MyObjectTypeTwo implements GeneralInterface, InterOne { /*...*/} 

class MyObjectTypeThr implements GeneralInterface, InterOne, InterTwo { /*...*/} 

У меня есть список, который держит эти MyObjectTypeXXX экземпляры

class ListHolder { 

    public static List<GeneralInterface> list = new ArrayList<>(); 

    ListHolder() { 

     list.add(new MyObjectTypeOne()); 
     list.add(new MyObjectTypeTwo()); 
     list.add(new MyObjectTypeTwo()); 
     // add any number of any of the types 
    } 
} 

и 20-40 функциональные интерфейсы. Вот 2 примера:

@FunctionalInterface 
public interface InterOne { 

    boolean onInterOne(); 

    static void iterate() { 

     for (GeneralInterface obj : ListHolder.list) { 
      if (obj instanceof InterOne) { 
       if (((InterOne) obj).onInterOne()) 
        System.out.println("yes"); 
      } 
     } 
    } 
} 

и

@FunctionalInterface 
public interface InterTwo { 

    boolean onInterOne(String string); 

    static void iterate(String string) { 

     for (GeneralInterface obj : ListHolder.list) { 
      if (obj instanceof InterTwo) { 
       if (((InterTwo) obj).onInterTwo(string)) 
        System.out.println("yes"); 
      } 
     } 
    } 
} 

В разных местах в коде мне нужно вызвать различные iterate методы:

InterTwo.iterate("S"); 
InterOne.iterate(); 

Моя проблема заключается в том, что мне нужно поддерживать iterate метод для всех функциональных интерфейсов, в то время как они эффективно выполняют одно и то же: проверяя, реализует ли этот объект этот интерфейс (отбрасывает его) и вызывает его только абстрактного метода с данными аргументами.

Есть ли способ, через синтаксис или дизайн, поддерживать только один метод, который делает это? Я знаю, что с отражением есть плохой способ сделать это (я показываю это просто, чтобы показать, что я сделал свое исследование, я не хочу его):

static void iterate(Class<?> clazz, Object arg) { 

    for (GeneralInterface obj : ListHolder.list) { 
     if (clazz.isAssignableFrom(obj.getClass())) { 
      Method[] methods = clazz.getMethods(); 
      Method functional; 
      for (Method m : methods) { 
       if (m.getModifiers() == Modifier.ABSTRACT) { 
        functional = m; 
        break; 
       } 
      } 
      if ((boolean) functional.invoke(obj, arg)) // cast arg or do some other trick 
       System.out.println("yes"); 
     } 
    } 
} 
+1

В вашем сценарии отражения вы сможете использовать параметры 'Object', чтобы он не был полностью работоспособен, не так ли? Или добавьте приведение в класс параметров, используемых в функциональном методе. –

+0

@YassinHajaj О пути отражения, да, в вызове будет какой-то притвор или какой-нибудь другой трюк. Это не так важно, так как это плохой путь. – user1803551

+0

Не могли бы вы объяснить, какова ваша фактическая проблема, которую вы пытаетесь решить, используя кучу интерфейсов? Кажется, это проблема XY: http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem – krokodilko

ответ

0

Я думаю, что ваш код имеет несколько точек которые нуждаются в улучшении, но я сосредоточен только на том, чтобы дать вам ответ на вашу конкретную проблему. Я думаю, что вам нужно передать этот общий метод промежуточного абстрактного класса:

abstract class MyObjectTypeAbstract { 
    abstract boolean onInter(String ... testString); 
    abstract boolean onInter(); 
    void iterate(String string) { 

     for (GeneralInterface obj : ListHolder.list) { 
      if (obj instanceof InterTwo) { 
       if (onInter(testString)) 
        System.out.println("yes"); 
      } 
     } 
    } 
    void iterate() { 

     for (GeneralInterface obj : ListHolder.list) { 
      if (obj instanceof InterTwo) { 
       if (onInter()) 
        System.out.println("yes"); 
      } 
     } 
    } 
} 

Что это делает, чтобы вы реализуете только то, что, кажется, отличается для каждого FunctionalInterface вы предоставили. Это метод onInter. Это кажется другим. Поэтому я сделал этот реферат. Остальное поделено. Я также вынул статические из методов итерации, чтобы они могли обращаться к различным реализациям метода onInter. Надеюсь, вам не понадобится эта статичность. Поэтому решение, которое я представляю, состоит в том, чтобы сделать ваши классы extendаннотация класс и реализовать интерфейсы как сейчас.

+1

Мои объекты уже расширяют класс, но, возможно, я могу интегрировать это поведение в него. – user1803551

+0

Я перечитал это, и вы не принимаете во внимание, что может быть несколько интерфейсов с одним и тем же аргументом абстрактного метода. Это не позволит вам перегружать вас. Кроме того, объединение всех методов в один класс - это то, чего я пытаюсь избежать, см. Http://programmers.stackexchange.com/questions/318164/what-is-a-good-design-to-couple-relate -методы-и ссылки. – user1803551

+0

Но вы действительно хотите избежать повторного кода? По крайней мере, это то, что я, хотя вы пытались сделать. Если вы действительно хотите сделать хорошее решение, я думаю, вам нужно избавиться от статической итерации(), которую вы сейчас имеете, и вам действительно нужно изменить способ создания этой архитектуры. Там просто нет хорошего решения сохранить текущий код. Если вы хотите идеальное решение, которое следует принципам [SOLID] (http://howtodoinjava.com/best-practices/5-class-design-principles-solid-in-java/), тогда вам нужно отказаться от того, что вы перезагрузите и снова запустите. Мое «решение» - это просто идея обойти его. –