1

私は頻繁に、Martin Fowler のプレゼンテーション モデルパターンを使用して Java Swing GUI を実装しています。

次に例を示します。

import java.awt.BorderLayout;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ListModel;

interface MainView {
    void configurationButtonAddActionListener(ActionListener actionListener);

    void directoryLabelSetText(String text);

    ListModel fileListGetModel();

    void setVisible(final boolean visible);
}

class MainFrame
        extends JFrame
        implements MainView {
    private final JButton configurationButton = new JButton("Configuration...");
    private final JLabel directoryLabel = new JLabel();
    private final JList fileList = new JList();

    public MainFrame(final String title) {
        super(title);

        final JPanel mainPanel = new JPanel(new BorderLayout());
        add(mainPanel);
        mainPanel.setBorder(BorderFactory.createEmptyBorder(12, 12, 12, 12));

        mainPanel.add(directoryLabel, BorderLayout.NORTH);
        mainPanel.add(new JScrollPane(fileList));
        mainPanel.add(configurationButton, BorderLayout.SOUTH);

        setSize(800, 600);
        setLocationRelativeTo(null);
    }

    @Override
    public void configurationButtonAddActionListener(final ActionListener actionListener) {
        configurationButton.addActionListener(actionListener);
    }

    @Override
    public void directoryLabelSetText(final String text) {
        directoryLabel.setText(text);
    }

    @Override
    public ListModel fileListGetModel() {
        return fileList.getModel();
    }
}

その後、インターフェイスは、ビューでのすべてのアクションの処理を担当するプレゼンター クラスに渡すことができます。テスト用にモック バージョンをプレゼンターに渡すことができます。ビューは非常にシンプルなので、理論的にはユニット テストを行う必要はありません。

私はClojureで以下を使用して同様のことをしようとしていますdefrecord:

(ns mainframe
 (:gen-class)
 (:import
   [java.awt BorderLayout]
   [javax.swing JButton JFrame JLabel JList JPanel JScrollPane]))

(if *compile-files*
  (set! *warn-on-reflection* true))

(defprotocol MainView
  (directory-label-set-text [this text])
  (set-visible [this visible]))

(defrecord mainframe [^JFrame frame
                      directory-label
                      file-list
                      configuration-button]
  MainView
  (directory-label-set-text [this text]
    (.setText directory-label text))
  (set-visible [this visible]
    (.setVisible frame visible)))

(defn create-main-frame
  [title]
  (let [directory-label (JLabel.)

        file-list (JList.)

        configuration-button (JButton. "Configuration...")

        main-panel (doto (JPanel. (BorderLayout.))
                     (.add directory-label BorderLayout/NORTH)
                     (.add (JScrollPane. file-list))
                     (.add configuration-button BorderLayout/SOUTH))

        frame (doto (JFrame.)
                (.setTitle title)
                (.setDefaultCloseOperation JFrame/EXIT_ON_CLOSE)
                (.add main-panel)
                (.setSize 800 600)
                (.setLocationRelativeTo nil))]
    (mainframe. frame directory-label file-list configuration-button)))

インターフェイスと「クラス」を実行するために私ができる唯一の方法は、 and を使用することdefprotocolですdefrecord。より良い方法はありますか?defrecordコンポーネント (JButton、JLabel、JList) を含む「フィールド」を非公開にする方法はありますか? 実装の詳細を公開するのは嫌いです。

4

1 に答える 1

3

deftypeこれらの実装の種類については、 の代わりにおそらく必要ですdefrecorddefrecordはデータに関するものですが、deftype一部のインターフェイスの背後にある核心を実装するために使用されます。これは少しあいまいに聞こえますが、 http://clojure.org/datatypesの私の解釈です。あなたのフレームは 2 番目のカテゴリに分類されると思います。

私は物事を隠そうとすることにあまり時間をかけません。型フィールドに触れないでください (インターフェイス関数内を除く)。型と対話するには、インターフェイス関数のみを使用してください。その場合、フィールドが技術的にプライベートかパブリックかは関係ありません。(繰り返しになりますが、 http://clojure.org/datatypesの意見に関するセクションを参照してください)

于 2011-04-27T12:45:29.727 に答える