Шаблон посетителей - это именно то, чего вы пытаетесь достичь.Тем не менее, «старый добрый полиморфизм» прекрасно подойдет для того, что вам нужно.Например:
abstract class BaseThing {
abstract public void doSomething();
}
class ThingA extends BaseThing {
public void doSomething() {
System.out.println("ThingA...");
}
}
class ThingB extends BaseThing {
public void doSomething() {
System.out.println("ThingB...");
}
}
class ThingC extends BaseThing {
public void doSomething() {
throw new UnsupportedOperationException("Cannot call this on ThingC");
}
}
, а затем
class ThingHandler {
public void doSomething(BaseThing thing) {
try {
thing.doSomething();
} catch (UnsupportedOperationException e) {
throw new IllegalArgumentException("Can't handle thing!");
}
}
}
Таким образом,
ThingHandler handler = new ThingHandler();
handler.doSomething(new ThingA()); // -> ThingA...
handler.doSomething(new ThingB()); // -> ThingB...
handler.doSomething(new ThingC()); // -> IllegalArgumentException: Can't handle thing!
Вы упомянули «нужно разобраться, что это за особая вещь»так что теперь все, что вам нужно, это иметь в своем BaseThing
абстрактный метод, который будет возвращать Comparator
, а каждый ThingA
и т. д. будет реализовывать его и возвращать соответствующий компаратор для ThingHandler
класс для сортировки.Каждая реализация BaseThing
может выполнять определенные операции или возвращать какое-либо значение, которое вам понадобится в ThingHandler
(вы можете даже передать экземпляр ThingHandler
в методе BaseThing.doSomething
...)
Но если Шаблон посетителя действительно то, что вам нужно, вот пример для вашей потребности:
interface IThing {
public void accept(ThingHandler handler);
}
interface IThingHandler {
public void visit(ThingA a);
public void visit(ThingB b);
//...
}
class ThingA implements IThing {
public void accept(IThingHandler h) {
h.visit(this);
}
public String getSomeValueA() {
return "Thing A";
}
}
class ThingB implements IThing {
public void accept(IThingHandler h) {
h.visit(this);
}
public String getSomeValueB() {
return "Thing B";
}
}
// ...
class ThingHandler implements IThingHandler {
public void visit(ThingA thing) {
// sort according to ThingA
System.out.println(thing.getSomeValueA() + " has visited");
doSomething(thing);
}
public void visit(ThingB thing) {
// sort according to ThingB
System.out.println(thing.getSomeValueB() + " has visited");
doSomething(thing);
}
private void doSomething(IThing thing) {
// do whatever needs to be done here
}
}
Тогда
IThingHandler handler = new ThingHandler();
new ThingA().accept(handler); // -> Thing A has visited
new ThingB().accept(handler); // -> Thing B has visited
//...
Но так как это означает сохранениеинтерфейс IThingHandler
каждый раз, когда реализуется новый класс IThing
, я предпочитаю предлагать первую модифицированную / упрощенную реализацию шаблона.Тем не менее, не стесняйтесь адаптировать шаблон для ваших нужд и не останавливайтесь, потому что он не точно выглядит как описанный шаблон посетителя.
Два
- «кто отвечает за выполнение операции?»
- «кто отвечает за хранение необходимых данных для выполнения операции?»
Я обычно предпочитаю хранить большую часть бетона в одном месте и обобщать в других местах;это помогает поддерживать (например, добавление и удаление функций).Хотя шаблон посетителя помогает централизовать работу в одном классе ...