Использование полей классов в функциях по умолчанию в абстрактных классах - PullRequest
3 голосов
/ 17 апреля 2020

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

Теперь по состоянию тока, чтобы осуществить это, я сделаю следующее

enum ServerType {
    primary,
    backup,
    idle
}
class ImportantClass {
   State myState;

   // Other fields

   void commonClassFunc() {
     if (state == idle) {
       idleFoo();
     } else if (state == primary) {
       primaryFoo();
     }
     ....
   }

   // Helper functions for State primary
   void primaryFoo() {
     // Access and mutate fields
   }
   ...

   // Helper functions for State backup
   void backupFoo() {
     // Access and mutate fields
   }
   ...

   // Helper functions for State idle
   void idleBar() {
     // Access and mutate fields
   }
   ...

}

Вы можете видеть, как это приведет к очень большому Определение класса и его состояние c будут разделены только комментариями.

Моя цель - сделать это более красноречивым способом. Я мог бы, например, создать классы Primary, Backup и Idle и сделать так, чтобы ImportantClass содержал один из этих классов, однако не позволил бы этим методам получить доступ к общим полям. Я хотел использовать интерфейсы, которые позволяют мне делать как class ImportantClass implements Primary {}, но, к сожалению, даже несмотря на то, что я могу определить метод primaryFoo в этом интерфейсе, этот метод все равно не сможет получить доступ к полям ImportantClass.

Делаете ли вы знаете, как я могу структурировать этот код так, чтобы я мог прекратить поведение этих трех состояний, между которыми важныйClass переключается при доступе к полям ImportantClass?

Ответы [ 2 ]

2 голосов
/ 17 апреля 2020

Один из вариантов решения проблемы будет следующим: Создайте новый класс (скажем, ImportantInfo) для хранения полей, которые являются общими для состояний: те общие поля, к которым вы хотите получить доступ из ImportantClass, и состояния.
Затем вы можете создать классы для каждого состояния по своему усмотрению и заставить их принимать ImportantInfo в качестве аргумента конструктора, каждый метод может работать с этими полями. Таким образом, свойства ImportantInfo должны иметь доступ c. Однако вы не нарушаете инкапсуляцию, поскольку можете сделать экземпляр ImportantInfo закрытым.
Для переключения между желаемым действием по отношению к текущему состоянию у вас должны быть классы, которые делают действие наследуемым от общего абстрактного класса. , Например, StateImplementor абстрактный класс, который построен из объекта ImportantInfo, и IdleImplementor, PrimaryImplementor, et c в качестве подклассов. StateImplementor будет иметь абстрактный метод Foo, который реализован в этих классах. Для переключения между реализациями у вас должен быть currentImplementor объект в ImportantClass и переключаться как:

void switchState(ServerType newState) {
    if (newState == ServerType.Idle)
        this.currentImplementor = new IdleImplementor(this.importantInfo);
}
1 голос
/ 17 апреля 2020

Мое общее чувство здесь таково, что, возможно, вам следует сделать ImportantClass общим родительским классом между классами, соответствующими трем состояниям:

public class ImportantClass {
    private State myState;

    // other common metadata + getters and setters
}

public class PrimaryClass extends ImportantClass {
    // fields specific to this class

    // Helper functions for State primary
    private void primaryFoo() {
    }
}

И так далее, с классами для двух других состояний.

Каждый из трех подклассов, хотя и не имеет прямого доступа к частному родительскому состоянию ImportantClass, по крайней мере сможет вызывать методы получения и установки для доступа и изменения этого состояния. Основная идея c заключается в том, чтобы переместить поведения (читай: методы), которые не принадлежат друг к другу, в отдельные классы.

...