0

I'm building a Spring application in which every entity(Person) which can perform 3 tasks, say, Walk, Talk & Think.

Since all of them are some sort of Person's capabilities, I'm thinking of making an interface Capability.java which will have a method performTask().

Above 3 classes will implement Capability.java & will also have their own set of other specific methods.

Since, these 3 classes are verbs, I'm making them as @Service, i.e.

  1. WalkServiceImpl.java
  2. TalkServiceImpl.java
  3. ThinkServiceImpl.java

Also, I'm thinking of making one @Controller - PersonController, which will call performTasks() of these 3 classes.

To use these classes in PersoneController, I'll have to autowire them. And as a general practice we should always @Autowire the interface.

But here the 3 classes have a common interface, with which I'll not be able to call performTaks() of all 3 services in the controller.

So, my question is, what should I do (A or B)?:

A. additionally make 3 separate interfaces, viz. WalkService, TalkService & ThinkService, which extends Capability.java and autowire these classes in controller?

B. Directly autowire WalkServiceImpl, TalkServiceImpl & ThinkServiceImpl in controller?

Luxspes
  • 6,268
  • 2
  • 28
  • 31
reiley
  • 3,759
  • 12
  • 58
  • 114
  • You must use only one interface, you can named the beans like this: http://stackoverflow.com/questions/5576128/how-to-overwrite-spring-service-beans-by-name-using-annotations-only – David Pérez Cabrera Sep 03 '16 at 19:09
  • 1
    Do you really need to be able to use these capabilities interchangeably? Otherwise, I think you're overengineering your application by creating the Capability interface. – Buhb Sep 03 '16 at 19:13
  • @DavidPérezCabrera, I read your suggested post, but still didn;t fully understand. Can you please help me with an example? – reiley Sep 03 '16 at 19:19

1 Answers1

2

If you wire the interface for one bean, you are effectivly saying, that you expect only one implementation to exist - or that the configuration takes care of the problems and leaves you with one primary candidate. Obviously, this is not what you want here.

The idea of wiring the three services explicitly is questionable, if you ask me. If you already know at design time, what specific services there will always be, why autowiring at all? Then you can hardcode them and be done with it. Autowiring is great if you want to give up control about the details. Using autowiring but forcing it to do exactly one very specific thing... Not very useful.

So, no, if there are many capabilities - think of the future, perhaps persons will also be able to swim, drive, jump... - then what you perhaps should try is to make some factory that can produce any type of capability - or better, get all available ones from Spring.

Why not simply wire the list of all beans implementing the interface?

@Autowired
private Set<Capability> capabilities;

Then the factory (or person, or whatever) can access all capabilities that exist. Perhaps the capabilities have some way to check to which person they apply?

Of course, what @Buhb said is very likely true, it sounds like a horribly overengineered solution, but obviously we are talking about some playing around, so why not.

Florian Schaetz
  • 10,454
  • 5
  • 32
  • 58