2015-04-09 4 views
2

Предположим, у меня есть файл, как это:Как отредактировать внутренний класс MouseAdapter?

import javax.swing.JPanel; 
import java.awt.event.MouseAdapter; 
public class Foo extends JPanel 
{ 
    private int m; 
    private int n; 
    private int o; 

    public Foo() 
    { 
     this.addMouseListener(new Bar()); 
    } 

    class Bar extends MouseAdapter 
    { 
     // ... 
     // methods here access and modify values of the private 
     // instance variables. 
     // ... 
    } 
} 

Очевидно, что я могу добавить простые аксессоров и мутаторов в Foo но становится утомительным быстро и полностью нарушает инкапсуляцию. Как я могу реорганизовать этот внутренний класс, сохранив минимум инкапсуляции?

+1

Есть ли причина, что вам нужно используйте внутренний класс вместо анонимного? –

+0

Да. Внутренний и внешний классы довольно большие (как более 200 строк кода каждый), так и мне нужно уменьшить размер этого файла. – zxgear

ответ

2

Если эти классы кажутся слишком большими, вы должны разделить их. Первым шагом их разделения было бы отказаться от использования частных переменных экземпляра внешнего класса. Вы могли бы, как вы говорите, добавить публичные геттеры и сеттеры, но лучше было бы, чтобы Foo реализовал публичный интерфейс Bar, и Bar просто поговорит с этим интерфейсом. И инициализируйте каждый бар самостоятельно.

public class Bar extends MouseAdapter { 
    public interface Caller { 
     void thingClicked(); 
     ... 
    } 
} 

public class Foo extends JPanel implements Bar.Caller { 
    ... 
} 

Так где сейчас в баре у вас есть что-то вроде:

public void mouseUp() { 
    m = m + 1; 
    n = 0 
} 

вы бы теперь

public void mouseUp() { 
    caller.thingClicked(); 
} 

и, в Foo:

public void thingClicked() { 
    m = m + 1; 
    n = 0 
} 

Это трудно сделайте это понятным без особых деталей, но basicall y ваш внешний класс отвечает на сообщения, и слушатель мыши несет ответственность только за доставку этих сообщений, а не за то, что происходит в ответ на них. В приведенных выше примерах, похоже, что это больше кода, чем у вас уже есть, но я подозреваю, что вы обнаружите, что резка его таким образом в конечном итоге приводит к меньшему количеству кода и, конечно, коду, который легче тестировать и повторно использовать.

+0

«но лучше было бы, чтобы Foo реализовал публичный интерфейс Bar» означает ли это, что Foo и Bar реализуют один и тот же интерфейс? – zxgear

+0

Я отредактировал ответ, чтобы показать объявление Bar.Caller; Отвечает ли это на ваш вопрос? –

+1

Да, я понимаю сейчас. – zxgear

1

Один из подходов состоит в том, чтобы поместить класс bar в новый файл и ввести все, что вам нужно там, в конструктор. Вам нужно будет изменить свои примитивные типы, например int, на объекты типа Integer. Затем вы можете создать класс Builder, который управляет конструкцией Foo и Bar. Предположим для простоты, что вам нужно и тот же экземпляр Baz во всех ваших Foo и Bar случаях:

class Builder { 
    // objects that both classes need are stored as member variables 
    // if you need multiple instances of baz you can also store a BazBuilder here 
    private Baz baz; 

    public Builder(Baz baz) { 
    this.baz=baz; 
    } 

    public Foo buildFoo() { 
    Foo foo = new Foo(baz); 
    return foo; 
    } 

    public Bar buildBar() { 
    Bar bar = new Bar(baz); 
    return bar; 
    } 
} 

Это только минималистичный пример, но это легко расширить. Builder#buildFoo() может принимать аргументы, необходимые в конструкторе Foo, а также для Bar.

EDIT Маленький пример того, что это может выглядеть с BazBuilder:

class BazBuilder { 

Baz build(int value) { 
    return new Baz(value); 
} 
} 

И в Builder вы можете использовать его так:

class Builder { 
    private BazBuilder bazBuilder; 

    public Build(BazBuilder bazBuilder) { 
    this.bazBuilder = bazBuilder; 
    } 

    public Foo buildFoo() { 
    Baz baz = bazBuilder.build(5); 
    Bar bar = new Bar(baz); 
    Foo foo = new Foo(baz); 
    foo.add(bar); 
    return foo; 
    } 
} 
+0

Почему мне нужно изменить все мои примитивные типы на объекты-обертки? – zxgear

+1

@JohnH Это действительно зависит от того, чего вы хотите достичь. Если вы используете примитивные типы, два значения будут независимыми. Поэтому, если вы измените значение в одном классе, значение в другом классе останется прежним. То, что я обычно делаю, это сделать пользовательскую оболочку, прочитать значения в одном классе и манипулировать ими в другой. Это не будет работать с примитивами. –

+0

Правда. Есть ли конкретное имя для этого шаблона проектирования? – zxgear

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