Вопрос по кодонаписанию
От: Тычеблин Китай  
Дата: 08.01.06 04:13
Оценка: 4 (1)
Привет Всем

Сначала думал оформить в контексте Вопрос по правильному кодонаписанию
Автор: leska
Дата: 06.01.06
потом передумал. У меня вопрос тоже по стилю но о другом.

Предлагаю обсудить то, как можно было бы более правильно и красиво реализовать подписку на собылия объекта и отказ от них.
то как это сделано в AWT/SWING например у Component
    public synchronized void addComponentListener(ComponentListener l)
    public synchronized void removeComponentListener(ComponentListener l)
    public synchronized ComponentListener[] getComponentListeners()

    public synchronized void addFocusListener(FocusListener l)
    public synchronized void removeFocusListener(FocusListener l)
    public synchronized FocusListener[] getFocusListeners()

    public void addHierarchyListener(HierarchyListener l)
    public void removeHierarchyListener(HierarchyListener l)
    public synchronized HierarchyListener[] getHierarchyListeners()

    public void addHierarchyBoundsListener(HierarchyBoundsListener l)
    public void removeHierarchyBoundsListener(HierarchyBoundsListener l)
    public synchronized HierarchyBoundsListener[] getHierarchyBoundsListeners()

    public synchronized void addKeyListener(KeyListener l)
    public synchronized void removeKeyListener(KeyListener l)
    public synchronized KeyListener[] getKeyListeners()

    public synchronized void addMouseListener(MouseListener l)
    public synchronized void removeMouseListener(MouseListener l)
    public synchronized MouseListener[] getMouseListeners()

    public synchronized void addMouseMotionListener(MouseMotionListener l)
    public synchronized void removeMouseMotionListener(MouseMotionListener l)
    public synchronized MouseMotionListener[] getMouseMotionListeners()

    public synchronized void addMouseWheelListener(MouseWheelListener l)
    public synchronized void removeMouseWheelListener(MouseWheelListener l)
    public synchronized MouseWheelListener[] getMouseWheelListeners()

    public synchronized void addInputMethodListener(InputMethodListener l)
    public synchronized void removeInputMethodListener(InputMethodListener l)
    public synchronized InputMethodListener[] getInputMethodListeners()

лично я нахожу откровенно корявым и загаживающим API. (нет? )

более элегантным решением могло бы стать что-то вроди
    public ComponentListener.Hub onComponentEvent=....
    public FocusListener.Hub onFocusEvent=....
    public HierarchyListener.Hub onHierarchyEvent=....

........

        public interface ComponentListener extends EventListener
    {
        public void componentResized(ComponentEvent e);
        public void componentMoved(ComponentEvent e);
        public void componentShown(ComponentEvent e);
        public void componentHidden(ComponentEvent e);
        
        public class Hub
        {
            public void add(ComponentListener c){};
            public void del(ComponentListener c){};
            public ComponentListener get(){};
        }
        
    }
........

таким образом использование будет выглядить так
......
comp.onComponentEvent.add(componentListener);//добавление обработчика
comp.onComponentEvent.del(componentListener);//удаление обработчика
comp.onComponentEvent.get().componentShown(componentEvent);//вызов (invoke) у всех зарег. обработчиков componentShown(ComponentEvent e)
.....

Но (!) как это может быть устроено внутри? что думаете?
Re: Вопрос по кодонаписанию
От: Airat Burganov Россия http://www.burganov.com
Дата: 08.01.06 08:34
Оценка:
Т>Предлагаю обсудить то, как можно было бы более правильно и красиво реализовать подписку на собылия объекта и отказ от них.
Т>то как это сделано в AWT/SWING например у Component
Т>лично я нахожу откровенно корявым и загаживающим API. (нет? )

Т>более элегантным решением могло бы стать что-то вроди

T> что думаете?

Мне больше нравится стандартное решение.
Кроме того ваше решение противоречит т.н. правилу Деметры, упоминание о котором можно встретить в книжке
С. Макконела "Совершенный код" (глава 6.3)

Избегайте опосредованных вызовов методов других классов.
Непосредственные связи довольно опасны. Опосредованные связи, такие как account.ContactPerson().DaytimeContactlnfo().PhoneNumberO, опасны еще больше. В связи с этим ученые сформулировали «Правило Деметры (Law of Demeter)» (Lieberherr and Holland, 1989), которое гласит, что Объект А может вызывать любые из собственнных методов. Если он создает Объект В, он может вызывать любые методы Объекта В, но ему не следует вызывать методы объектов, возвращаемых Объектом В. В нашем случае это означает, что вызов account.ContactPerson() приемлем, однако вызова account.ContactPerson().DaytimeContactlnfo() следовало бы избежать.

Re[2]: Вопрос по кодонаписанию
От: Тычеблин Китай  
Дата: 08.01.06 09:06
Оценка:
Здравствуйте, Airat Burganov, Вы писали:

AB>Мне больше нравится стандартное решение.


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

AB>Кроме того ваше решение противоречит т.н. правилу Деметры,


ну, в общем без проблем, если хочется чему-то удовлетворять или соответствовать, можно и через промежуточную переменную.
//а мине вот так писать ндравилось фсигда ;) 
new Thread()
{
    public void run()
    {
        asych_call();
    }

}.start();

только прошу понять меня правильно, я ведь не умничать пытаюсь.
просто предлагаю тем, кому это интересно совместно задуматься, исследовать эту проблемму.
Re[3]: Вопрос по кодонаписанию
От: Airat Burganov Россия http://www.burganov.com
Дата: 08.01.06 09:51
Оценка:
AB>>Мне больше нравится стандартное решение.

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

Я честно говоря у вашего решения плюсов не вижу. В плане реализации писать надо не меньше. Интуитивно не понятно. Какие у вас плюсы? Минусы — введение дополнительных сущностей Hub на какждый новый листенер, не прозрачная иерархия вызовов.

AB>>Кроме того ваше решение противоречит т.н. правилу Деметры,

Т>ну, в общем без проблем, если хочется чему-то удовлетворять или соответствовать, можно и через промежуточную переменную.
Да нет, можно и не соответсвовать, к тому же правило малоизвестное. Но почему-то обычно когда я вижу в коде множество вызовов, например таких
myFrame.myTable.getModel().getRow().getЧтонибудьеще()

то вскоре оказывается, что микроархитектура этого кода очень кривая.
Re[4]: Вопрос по кодонаписанию
От: Тычеблин Китай  
Дата: 08.01.06 10:59
Оценка:
Здравствуйте, Airat Burganov, Вы писали:

AB>Я честно говоря у вашего решения плюсов не вижу. В плане реализации писать надо не меньше. Интуитивно не понятно. Какие у вас плюсы? Минусы — введение дополнительных сущностей Hub на какждый новый листенер, не прозрачная иерархия вызовов.


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

вместо
    public synchronized void addComponentListener(ComponentListener l)
    public synchronized void removeComponentListener(ComponentListener l)
    public synchronized ComponentListener[] getComponentListeners()

будет в API объекта генерирующего события останется только
    public ComponentListener.Hub onComponentEvent=....

onComponentEvent — сущность, функцией которой является регистрация получателей собылтий.
благодоря ей происходит очистка API объекта от утилитарных методов
AB>Но почему-то обычно когда я вижу в коде множество вызовов, например таких
AB>
AB>myFrame.myTable.getModel().getRow().getЧтонибудьеще()
AB>

AB>то вскоре оказывается, что микроархитектура этого кода очень кривая.

причем тут архитектура? то о чем Вы говорите — это уже использование некоторой архитектуры.
такую последовательность вызовов несможет предотвратить ни одна архитектура, ну, кроме разве той, согласно которой методу запрещено возвращать ссылку на объект. но это не идеология JAVA, вроди так
Re[5]: Вопрос по кодонаписанию
От: Airat Burganov Россия http://www.burganov.com
Дата: 08.01.06 11:34
Оценка:
AB>>Я честно говоря у вашего решения плюсов не вижу. В плане реализации писать надо не меньше. Интуитивно не понятно. Какие у вас плюсы? Минусы — введение дополнительных сущностей Hub на какждый новый листенер, не прозрачная иерархия вызовов.

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


Т>вместо

Т>
Т>    public synchronized void addComponentListener(ComponentListener l)
Т>    public synchronized void removeComponentListener(ComponentListener l)
Т>    public synchronized ComponentListener[] getComponentListeners()
Т>

для демонстрации synchronized или надо было убирать, либо делать synchronized и свое api.

Т>будет в API объекта генерирующего события останется только

Т>
Т>    public ComponentListener.Hub onComponentEvent=....
Т>

Т>onComponentEvent — сущность, функцией которой является регистрация получателей собылтий.
Т>благодоря ей происходит очистка API объекта от утилитарных методов
Пожалуйста более подробнее. И ответьте в чем польза использования именно такого объекта. Где плюсы? Упомянутые мною минусы сохраняются и не объяснены. Ваша реализация непрозрачная. Как написать addComponentListener, removeComponentListener, getComponentListeners в 6-8 строк я знаю, а как писать ваш листенер?
  public interface ComponentListener extends EventListener
    {
        public void componentResized(ComponentEvent e);
        public void componentMoved(ComponentEvent e);
        public void componentShown(ComponentEvent e);
        public void componentHidden(ComponentEvent e);
        
        public class Hub
        {
            public void add(ComponentListener c){};
            public void del(ComponentListener c){};
            public ComponentListener get(){};
        }
        
    }

Насколько я понимаю меоды add,del,get реализуются в интерфейсе? а инкапсуляция? А если я закочу расширить этот компонент листенер, всюду делать свои hub'ы? Ни о чем этом вы похоже не думали.

Ссылки на то, что главное — это идея не принимаются. Идеи никакой тут нет, одна бессмыслица, набор необоснованных утверждений. Вы сами пробовали пользоваться тем, что написали? Хоть один реальный листенер покажите.

Т>причем тут архитектура? то о чем Вы говорите — это уже использование некоторой архитектуры.

Т>такую последовательность вызовов несможет предотвратить ни одна архитектура, ну, кроме разве той, согласно которой методу запрещено возвращать ссылку на объект. но это не идеология JAVA, вроди так
микроархитектура. Паттерны спасут.
Re[6]: Вопрос по кодонаписанию
От: Тычеблин Китай  
Дата: 08.01.06 12:47
Оценка:
Здравствуйте, Airat Burganov, Вы писали:

AB>микроархитектура. Паттерны спасут.


несколько раз перечитал Ваши ответы, долго думал.
Вы либо не внимательны либо я совсем плохо объясняю.
Re: Вопрос по кодонаписанию
От: Blazkowicz Россия  
Дата: 10.01.06 09:40
Оценка: +1
Здравствуйте, Тычеблин, Вы писали:

Т>Сначала думал оформить в контексте Вопрос по правильному кодонаписанию
Автор: leska
Дата: 06.01.06
потом передумал. У меня вопрос тоже по стилю но о другом.


Т>Предлагаю обсудить то, как можно было бы более правильно и красиво реализовать подписку на собылия объекта и отказ от них.

Т>то как это сделано в AWT/SWING например у Component

Т>таким образом использование будет выглядить так

comp.onComponentEvent.add(componentListener);//добавление обработчика
comp.onComponentEvent.del(componentListener);//удаление обработчика
comp.onComponentEvent.get().componentShown(componentEvent);//вызов (invoke) у всех зарег. обработчиков

Т>Но (!) как это может быть устроено внутри? что думаете?

Уж не делегаты ли из C# вы нам пытаетесь подсунуть?
Re[2]: Вопрос по кодонаписанию
От: Тычеблин Китай  
Дата: 10.01.06 10:19
Оценка:
Здравствуйте, Blazkowicz, Вы писали:

B>Здравствуйте, Тычеблин, Вы писали:


Т>>Сначала думал оформить в контексте Вопрос по правильному кодонаписанию
Автор: leska
Дата: 06.01.06
потом передумал. У меня вопрос тоже по стилю но о другом.


Т>>Предлагаю обсудить то, как можно было бы более правильно и красиво реализовать подписку на собылия объекта и отказ от них.

Т>>то как это сделано в AWT/SWING например у Component

Т>>таким образом использование будет выглядить так

B>
B>comp.onComponentEvent.add(componentListener);//добавление обработчика
B>comp.onComponentEvent.del(componentListener);//удаление обработчика
B>comp.onComponentEvent.get().componentShown(componentEvent);//вызов (invoke) у всех зарег. обработчиков

Т>>Но (!) как это может быть устроено внутри? что думаете?

B>Уж не делегаты ли из C# вы нам пытаетесь подсунуть?


неа. оно конечно внешне (текстово) похоже on(ля-ля-ля)Event. но конечно это не делегаты, это больше попытка очистить API от разнообразных утилитарных методов имеющих отношение не столько к самому объекту, а к процессу регистрации обработчиков сбытий объекта.
к стати уже кой чего наизобретал, если сочту это не смешным и жизнеспособным выложу, отпинайте
Re[3]: Вопрос по кодонаписанию
От: Lucker Беларусь http://lucker.intervelopers.com/
Дата: 10.01.06 10:25
Оценка:
Здравствуйте, Тычеблин, Вы писали:

B>>Уж не делегаты ли из C# вы нам пытаетесь подсунуть?


Т>неа. оно конечно внешне (текстово) похоже on(ля-ля-ля)Event. но конечно это не делегаты, это больше попытка очистить API от разнообразных утилитарных методов имеющих отношение не столько к самому объекту, а к процессу регистрации обработчиков сбытий объекта.

Ну по этому поводу изобретать ничего не стоит, тем более что это что-то практически настолько-же прямое, насколько иоригинальное решение. Имя этим (как и многим другим) "утилитарным методам" — аспекты. Методы работы с аспектами, и конкретные реалиизации АОП (аспектно-ориентированного программирования) для java есть (например, aspectJ) и успешно применяются. Так что думаю если и рыть куда — то именно туда.
#333355130
Re[3]: Вопрос по кодонаписанию
От: Blazkowicz Россия  
Дата: 10.01.06 10:26
Оценка:
Здравствуйте, Тычеблин, Вы писали:

Т>неа. оно конечно внешне (текстово) похоже on(ля-ля-ля)Event. но конечно это не делегаты

Ну а делегаты "внутренне" это слушатели в Java. Так в чем внутреннее различие того что предолжено с делагатами?

Т>это больше попытка очистить API от разнообразных утилитарных методов имеющих отношение не столько к самому объекту, а к процессу регистрации обработчиков сбытий объекта.

Ну а делегаты не тоже ли самое?

Т>к стати уже кой чего наизобретал, если сочту это не смешным и жизнеспособным выложу, отпинайте

Ждем с нетерпением.
Re[4]: Вопрос по кодонаписанию
От: Тычеблин Китай  
Дата: 10.01.06 10:39
Оценка:
Здравствуйте, Blazkowicz, Вы писали:

B>Здравствуйте, Тычеблин, Вы писали:


Т>>неа. оно конечно внешне (текстово) похоже on(ля-ля-ля)Event. но конечно это не делегаты

B>Ну а делегаты "внутренне" это слушатели в Java. Так в чем внутреннее различие того что предолжено с делагатами?

Т>>это больше попытка очистить API от разнообразных утилитарных методов имеющих отношение не столько к самому объекту, а к процессу регистрации обработчиков сбытий объекта.

B>Ну а делегаты не тоже ли самое?

впервые столкнувшись с делигатами в Visual Java 6.0( к стати класная фича) я понял что делигаты это попытка решения обширного числа проблемм.
то что происходит очистка API от утилитарных методов подписки и удаления обработчиков событий (тема топика) это далеко не самое главное — так, побочный продукт (конечно нужный).

главное это возможность передачи указателя на метод сигнатура которого соответствует требуемому.
и не важно ни название метода не область видимости. сейчас вспоминая войну сана и микрософта на эту тему понимаешь какие сановцы были неадекватно воинствующие. особенно глядя на те изменения которые они же внесли в JDK 1.5. лучше б делигаты добавили
Re[5]: Вопрос по кодонаписанию
От: Blazkowicz Россия  
Дата: 10.01.06 10:50
Оценка:
Здравствуйте, Тычеблин, Вы писали:

Т>впервые столкнувшись с делигатами в Visual Java 6.0( к стати класная фича) я понял что делигаты это попытка решения обширного числа проблемм.

Т>то что происходит очистка API от утилитарных методов подписки и удаления обработчиков событий (тема топика) это далеко не самое главное — так, побочный продукт (конечно нужный).
Прошу прощения за снобизм, но все же "делегат", и уж никак не "Visual Java 6.0", а скорее всего
"Visual J++ 6.0"

Т>главное это возможность передачи указателя на метод сигнатура которого соответствует требуемому.

Дык тут, ИМХО без рефлексии, либо аспектов не обойтись.

Т>и не важно ни название метода не область видимости. сейчас вспоминая войну сана и микрософта на эту тему понимаешь какие сановцы были неадекватно воинствующие. особенно глядя на те изменения которые они же внесли в JDK 1.5. лучше б делигаты добавили

Гугл по вопросу делегатов в Java выдаёт довольно много ссылок. Видел даже какую-то реализацию через аннотации.
Re: Вопрос по кодонаписанию
От: dshe  
Дата: 10.01.06 11:20
Оценка:
Здравствуйте, Тычеблин, Вы писали:

Т>Привет Всем


Т>Сначала думал оформить в контексте Вопрос по правильному кодонаписанию
Автор: leska
Дата: 06.01.06
потом передумал. У меня вопрос тоже по стилю но о другом.


Т>таким образом использование будет выглядить так

Т>
Т>......
Т>comp.onComponentEvent.add(componentListener);//добавление обработчика
Т>comp.onComponentEvent.del(componentListener);//удаление обработчика
Т>comp.onComponentEvent.get().componentShown(componentEvent);//вызов (invoke) у всех зарег. обработчиков componentShown(ComponentEvent e)
Т>.....
Т>

Т>Но (!) как это может быть устроено внутри? что думаете?

Я тоже задумывался об этом. У меня получилось такое
package muticast;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;

/**
 * @author dshe
 *
 */
public final class Multicast<T> {
    private static final Map<Class<?>, Object> DEF_VALUES_CLASS_TO_OBJECT;
    static {
        DEF_VALUES_CLASS_TO_OBJECT = new HashMap<Class<?>, Object>();
        DEF_VALUES_CLASS_TO_OBJECT.put(boolean.class, Boolean.FALSE);
        DEF_VALUES_CLASS_TO_OBJECT.put(byte.class, new Byte((byte) 0));
        DEF_VALUES_CLASS_TO_OBJECT.put(short.class, new Short((short) 0));
        DEF_VALUES_CLASS_TO_OBJECT.put(char.class, new Character('\0'));
        DEF_VALUES_CLASS_TO_OBJECT.put(int.class, new Integer(0));
        DEF_VALUES_CLASS_TO_OBJECT.put(long.class, new Long(0L));
        DEF_VALUES_CLASS_TO_OBJECT.put(float.class, new Float(0f));
        DEF_VALUES_CLASS_TO_OBJECT.put(double.class, new Double(0d));
    }

    class Handler implements InvocationHandler {
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Object[] array = _list.toArray();
            Throwable thrown = null;
            for(int i = 0, n = array.length; i < n; ++i) {
                try {
                    method.invoke(array[i], args);
                }
                catch(IllegalAccessException exc) {
                    throw (Error) new IllegalAccessError().initCause(exc);
                }
                catch(InvocationTargetException exc) {
                    thrown = exc.getTargetException();
                }
            }
            // rethrow last occured exception
            if(thrown != null)
                throw thrown;
            // we cannot return null if method returns primitive value
            // thus we lookup default value is a table.
            return DEF_VALUES_CLASS_TO_OBJECT.get(method.getReturnType());
        }
    }

    private final List<T> _list;
    private final Class<T> _iface;
    private final T _proxy;

    private Multicast(Class<T> iface) {
        _list = new Vector<T>();
        _iface = iface;
        // unchecked cast: dont worry
        _proxy = (T) Proxy.newProxyInstance(iface.getClassLoader(), new Class[] { iface }, new Handler());
    }

    // static factory method is just for convenient type inference
    public static <U> Multicast<U> create(Class<U> iface) {
        return new Multicast<U>(iface);
    }

    public T fire() {
        return _proxy;
    }

    public void add(T obj) {
        if(!_iface.isInstance(obj))
            throw new IllegalArgumentException("obj : " + obj);
        _list.add(obj);
    }

    public void remove(T obj) {
        if(!_iface.isInstance(obj))
            throw new IllegalArgumentException("obj : " + obj);
        _list.remove(obj);
    }
}


И использование (имена методов, правда, немного поменял)
        Multicast<Runnable> multicast = Multicast.create(Runnable.class);
        Runnable a = new Runnable() {
            public void run() {
                System.out.println("one");
            }
        };
        Runnable b = new Runnable() {
            public void run() {
                System.out.println("two");
            }
        };
        multicast.add(a);
        multicast.add(b);
        multicast.fire().run();
        multicast.remove(b);
        multicast.fire().run();
--
Дмитро
Re[2]: Вопрос по кодонаписанию
От: dshe  
Дата: 10.01.06 11:40
Оценка:
Здравствуйте, Airat Burganov, Вы писали:

Т>>Предлагаю обсудить то, как можно было бы более правильно и красиво реализовать подписку на собылия объекта и отказ от них.

Т>>то как это сделано в AWT/SWING например у Component
Т>>лично я нахожу откровенно корявым и загаживающим API. (нет? )

Т>>более элегантным решением могло бы стать что-то вроди

T>> что думаете?

AB>Мне больше нравится стандартное решение.

AB>Кроме того ваше решение противоречит т.н. правилу Деметры, упоминание о котором можно встретить в книжке
AB>С. Макконела "Совершенный код" (глава 6.3)
AB>

AB>Избегайте опосредованных вызовов методов других классов.
AB>Непосредственные связи довольно опасны. Опосредованные связи, такие как account.ContactPerson().DaytimeContactlnfo().PhoneNumberO, опасны еще больше. В связи с этим ученые сформулировали «Правило Деметры (Law of Demeter)» (Lieberherr and Holland, 1989), которое гласит, что Объект А может вызывать любые из собственнных методов. Если он создает Объект В, он может вызывать любые методы Объекта В, но ему не следует вызывать методы объектов, возвращаемых Объектом В. В нашем случае это означает, что вызов account.ContactPerson() приемлем, однако вызова account.ContactPerson().DaytimeContactlnfo() следовало бы избежать.


Вообще-то, не мешало бы уточнить, чем именно опасны непосредственные связи и от чего правило Деметры предохраняет. Насколько я понимаю, правилу Деметры необходимор следовать для того, чтобы информация о "структурных" деталях реализации одного класса не расползалась по всей системе (приложению). Что же касается двух вариантов подписки
1. классический
comp.addComponentListener(componentListener);
comp.removeComponentListener(componentListener);
comp.fireComponentShown(componentEvent);

2. "хитрый"
comp.onComponentEvent.add(componentListener);
comp.onComponentEvent.del(componentListener);
comp.onComponentEvent.get().componentShown(componentEvent);


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

Однако, если реализовать подписку классическим вариантом, то можно заметить, что много кода буквально дублируется. Код подписки для различных listener'ов похож до безобразия. Поэтому было бы неплохо его написать один раз и потом использовать (а не переписывать для каждого типа listener'а заново).
--
Дмитро
Re[3]: Вопрос по кодонаписанию
От: Тычеблин Китай  
Дата: 10.01.06 12:17
Оценка: :)
Здравствуйте, dshe, Вы писали:

D>Однако, если реализовать подписку классическим вариантом, то можно заметить, что много кода буквально дублируется. Код подписки для различных listener'ов похож до безобразия. Поэтому было бы неплохо его написать один раз и потом использовать (а не переписывать для каждого типа listener'а заново).


спасибо дружище за понимание, а то, получая бессмысленные ответы на вопросы которых я не задавал, я уже начал сомневаться в своей способности объяснять
Re[2]: Вопрос по кодонаписанию
От: Тычеблин Китай  
Дата: 10.01.06 12:21
Оценка:
Здравствуйте, dshe, Вы писали:

D
D>И использование (имена методов, правда, немного поменял)
D>
D>        Multicast<Runnable> multicast = Multicast.create(Runnable.class);
D>        Runnable a = new Runnable() {
D>            public void run() {
D>                System.out.println("one");
D>            }
D>        };
D>        Runnable b = new Runnable() {
D>            public void run() {
D>                System.out.println("two");
D>            }
D>        };
D>        multicast.add(a);
D>        multicast.add(b);
D>        multicast.fire().run();
D>        multicast.remove(b);
D>        multicast.fire().run();
D>


да, точно Multicast как же я это забыл
Re[4]: Вопрос по кодонаписанию
От: Airat Burganov Россия http://www.burganov.com
Дата: 10.01.06 12:41
Оценка:
Здравствуйте, Тычеблин, Вы писали:

Т>спасибо дружище за понимание, а то, получая бессмысленные ответы на вопросы которых я не задавал, я уже начал сомневаться в своей способности объяснять

C тем что написал dshe я согласен, а ни одного ответа на мои вопросы от вас не получил.
Вопросы вы сами не задавали, так что на что отвечать мне — не понятно.

В вашей способности объяснять и понимать я уже не сомневаюсь. Ее просто нет.
Re[3]: Вопрос по кодонаписанию
От: Airat Burganov Россия http://www.burganov.com
Дата: 10.01.06 12:53
Оценка: 1 (1)
D>Вообще-то, не мешало бы уточнить, чем именно опасны непосредственные связи и от чего правило Деметры предохраняет. Насколько я понимаю, правилу Деметры необходимор следовать для того, чтобы информация о "структурных" деталях реализации одного класса не расползалась по всей системе (приложению). Что же касается двух вариантов подписки
D>1. классический
D>
D>comp.addComponentListener(componentListener);
D>comp.removeComponentListener(componentListener);
D>comp.fireComponentShown(componentEvent);
D>

D>2. "хитрый"
D>
D>comp.onComponentEvent.add(componentListener);
D>comp.onComponentEvent.del(componentListener);
D>comp.onComponentEvent.get().componentShown(componentEvent);
D>


D>То они в равной степени предоставляют "структурную" информацию. Оба эти варианта говорят о том, что comp позволяет подписаться на определенное событие.

(Не касаясь того, как это будет реализованно)
Да.. структурно. Но вас не смущает то, что onComponentEvent — public переменная?

D>Однако, если реализовать подписку классическим вариантом, то можно заметить, что много кода буквально дублируется. Код подписки для различных listener'ов похож до безобразия. Поэтому было бы неплохо его написать один раз и потом использовать (а не переписывать для каждого типа listener'а заново).

Вот это действительно очень надоедливая штука. Правда есть EventListenerList, который во-многом позволяет смириться с этим.
Re[3]: Вопрос по кодонаписанию
От: Airat Burganov Россия http://www.burganov.com
Дата: 10.01.06 12:57
Оценка: -1 :)
Т>да, точно Multicast как же я это забыл
интересно, как это вы могли это помнить? dshe только представил реализацию, а вы уже о ней в курсе
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.