2014-12-24 2 views
0

у меня есть один Worker интерфейс с одним методом:Инициирования объекта с переменным типом

interface Worker { 
    public void work() 
} 

У меня 2 классов, которые реализуют Worker,

class RoadWorker implements Worker { 
    public void setPropertyA() {} 
    public void work() {} 
} 

еще один,

class GardenWorker implements Worker { 
    public void setPropertyB() {} 
    public void work() {} 
} 

В мой класс Application - на основе некоторого входного флага - я хочу создать экземпляр одного спецификатора IC тип работника ...

class Application { 
    // flag 
    String whichWorker = "Road"; 

    // instantiate 
    if (whichWorker == "Road") { 
     RoadWorker worker = new RoadWorker(); 
     worker.setPropertyA(); 
    } else { 
     GardenWorker worker = new GardenWorker(); 
     worker.setPropertyB(); 
    } 

    // use 
    worker.work(); <----- OF COURSE THIS DOES NOT WORK (no reference) 

Итак, я попытался это -

class Application { 
    // flag 
    String whichWorker = "Road"; 
    Worker worker; 

    // instantiate 
    if (whichWorker == "Road") { 
     worker = new RoadWorker(); 
     worker.setPropertyA(); <----- DOES NOT WORK 
    } else { 
     worker = new GardenWorker(); 
     worker.setPropertyB(); <----- DOES NOT WORK 
    } 

    // use 
    worker.work(); 

Мой вопрос - как я разрабатываю свою программу, чтобы выполнить это требование? Я знаю, что один грубый вариант заключается в том, чтобы определить рабочего как Object, но тогда мне придется делать множество партий различного типа, которые мне не нужны. Может кто-нибудь предложить?

+0

** Не использовать == для сравнения строк !!!! ** – ajb

+0

@ajb - ок, спасибо за указание, что из – hashbrown

ответ

1

Используйте конструкторы для установки свойств или заводского рисунка.

Первое решение проще, но имеет свои пределы:

interface Worker { 
    public void work() 
} 

class RoadWorker implements Worker { 
    RoadWorker(PropertyA property) { 
    this.property = property; 
    } 
} 

void foo() { 
    Worker worker = null; 

    if (whichWorker.equals("road")) { 
    worker = new RoadWorker(property); 
    } 

    worker.work(); 
} 

Две боковые ноты:

  • не сравнить вещи с ==, использование равняется вместо
  • использовать Enum вместо что строка для переключения рабочего типа, они существуют для этой цели

Если вы больше гибкости, тогда может быть более подходящим factory method pattern.

2
Worker anyworker = null; 
if ("Road".equals(whichWorker)) { 
    RoadWorker worker = new RoadWorker(); 
    worker.setPropertyA(); 
    anyworker = worker; 
} else { 
    GardenWorker worker = new GardenWorker(); 
    worker.setPropertyB(); 
    anyworker = worker; 
} 

Или передать конкретные значения свойств в конструкторе подкласса.

+0

Спасибо. Это выглядит просто для меня. Знаете ли вы, что такое преимущество/преимущество этого подхода при передаче значений через подход конструктора? – hashbrown

1

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

RoadWorker:

class RoadWorker implements Worker { 
    public RoadWorker() { 
     this.setPropertyA(); 
    } 

    public void setPropertyA() {} 
    public void work() {} 
} 

GardenWorker:

class GardenWorker implements Worker { 
    public GardenWorker() { 
     this.setPropertyB(); 
    } 

    public void setPropertyB() {} 
    public void work() {} 
} 

Затем удалите эти вызовы на setProperty методы в вашей, если заявление:

class Application { 
    // flag 
    String whichWorker = "Road"; 
    Worker worker; 

    // instantiate 
    if (whichWorker.equals("Road")) { 
     worker = new RoadWorker(); 
    } else { 
     worker = new GardenWorker(); 
    } 

    // use 
    worker.work(); 

Примечание: Я изменил whichWorker == "Road" к whichWorker.equals("Road"), потому что для сравнения строк y ou необходимо использовать equals вместо ==.

0

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

Например

if (whichWorker == "Road") { 
    worker = new RoadWorker(); 
    ((RoadWorker)worker).setPropertyA(); 
} else { 
    worker = new GardenWorker(); 
    ((GardenWorker)worker).setPropertyB(); 
} 

Это должно работать

+0

Я действительно не хотел использовать кастинг любого типа ... – hashbrown

Смежные вопросы