【问题标题】:I need to separate my DOM from "persistence layer"我需要将我的 DOM 与“持久层”分开
【发布时间】:2014-04-01 13:23:41
【问题描述】:

我创建了一个引用用户列表的应用程序,从 XML 文件分配到 JTree 组件,然后可以相应地查看和编辑。到目前为止我的代码:

public class DomainModel extends JFrame {

    private JTree tree;
    private String fileSource = "users.xml";
    private NodeList listOfUsers;
    private String objID;

    private JTextField textName;
    private JTextField textAge;
    private JTextField textDOB;
    private JButton editBtn;

    private JTextField textEditName;
    private JTextField textEditAge;
    private JTextField textEditDOB;
    private JButton saveBtn;
    private JButton cancelBtn;

    public DomainModel() {

        createGUI();
    }

    public void createGUI() {

        JPanel mainPanel = new JPanel();
        mainPanel.setLayout(new GridLayout(1, 2));

        JPanel leftPanel = new JPanel();
        leftPanel.setLayout(new GridLayout(1, 1));
        leftPanel.setBorder(BorderFactory.createCompoundBorder(
                BorderFactory.createTitledBorder("Domain Model"),
                BorderFactory.createEmptyBorder(10, 10, 10, 10)));

        createTree();

        tree.setLayout(new GridLayout(1, 1));
        tree.setBorder(new EmptyBorder(10, 10, 10, 10));
        tree.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() {

            public void valueChanged(TreeSelectionEvent e) {

                nodeChange(e);
            }
        });

        JPanel rightPanel = new JPanel();
        rightPanel.setLayout(new GridLayout(2, 1));

        JPanel detailsPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        detailsPanel.setBorder(BorderFactory.createCompoundBorder(
                BorderFactory.createTitledBorder("Node Details"),
                BorderFactory.createEmptyBorder(5, 5, 5, 5)));

        JLabel labelName = new JLabel("Name");
        JLabel labelAge = new JLabel("Age");
        JLabel labelDOB = new JLabel("DOB");

        textName = new JTextField(15);
        textAge = new JTextField(15);
        textDOB = new JTextField(15);

        editBtn = new JButton("Edit");
        editBtn.addActionListener(new ButtonListener());

        detailsPanel.add(labelName);
        detailsPanel.add(textName);
        detailsPanel.add(labelAge);
        detailsPanel.add(textAge);
        detailsPanel.add(labelDOB);
        detailsPanel.add(textDOB);
        detailsPanel.add(editBtn);

        JPanel editPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        editPanel.setBorder(BorderFactory.createCompoundBorder(
                BorderFactory.createTitledBorder("Edit Node"),
                BorderFactory.createEmptyBorder(5, 5, 5, 5)));

        JLabel labelEditName = new JLabel("Name");
        JLabel labelEditAge = new JLabel("Age");
        JLabel labelEditDOB = new JLabel("DOB");

        textEditName = new JTextField(15);
        textEditAge = new JTextField(15);
        textEditDOB = new JTextField(15);

        saveBtn = new JButton("Save");
        saveBtn.addActionListener(new ButtonListener());

        cancelBtn = new JButton("Cancel");
        cancelBtn.addActionListener(new ButtonListener());

        editPanel.add(labelEditName);
        editPanel.add(textEditName);
        editPanel.add(labelEditAge);
        editPanel.add(textEditAge);
        editPanel.add(labelEditDOB);
        editPanel.add(textEditDOB);
        editPanel.add(saveBtn);
        editPanel.add(cancelBtn);

        leftPanel.add(new JScrollPane(tree));
        rightPanel.add(detailsPanel);
        rightPanel.add(editPanel);
        mainPanel.add(leftPanel);
        mainPanel.add(rightPanel);
        mainPanel.setBorder(new EmptyBorder(10, 10, 10, 10));
        add(mainPanel);

        nullDetails();
        nullEdit();

        setTitle("Domain Model Example");
        setSize(525, 350);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setResizable(false);
    }

    public void createTree(){

        DefaultMutableTreeNode root = new DefaultMutableTreeNode("users");

        try {

            DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
            Document doc = docBuilder.parse(new File(fileSource));

            listOfUsers = doc.getElementsByTagName("user"); 

            // for each user in the node list, add it to the JTree
            for (int i = 0; i < listOfUsers.getLength(); i++) {

                Element el = (Element) listOfUsers.item(i);
                String id = el.getAttribute("id");
                File file = new File(id);
                DefaultMutableTreeNode node = new DefaultMutableTreeNode(file);
                root.add(node);
            }

            tree = new JTree(root);

        } catch (Exception e) {

            e.printStackTrace();
        }
    }

    public void nodeChange(TreeSelectionEvent e) {

        nullDetails();
        nullEdit();

        objID = e.getPath().getLastPathComponent().toString();

        // for each user in the node list, find an ID match
        for (int i = 0; i < listOfUsers.getLength(); i++) {

            Element el = (Element) listOfUsers.item(i);
            String strID = el.getAttribute("id");

            // if an ID match has been found, display it's details
            if (objID.equals(strID)) {

                String strName = el.getElementsByTagName("name").item(0).getTextContent();
                String strAge= el.getElementsByTagName("age").item(0).getTextContent();
                String strDOB = el.getElementsByTagName("dob").item(0).getTextContent();

                textName.setText(strName);
                textAge.setText(strAge);
                textDOB.setText(strDOB);
                editBtn.setEnabled(true);
                break;
            }
        }
    }

    public void nullDetails() {

        textName.setText(null);
        textAge.setText(null);
        textDOB.setText(null);

        textName.setEnabled(false);
        textAge.setEnabled(false);
        textDOB.setEnabled(false);

        editBtn.setEnabled(false);
    }

    public void nullEdit() {

        textEditName.setText(null);
        textEditAge.setText(null);
        textEditDOB.setText(null);

        textEditName.setEnabled(false);
        textEditAge.setEnabled(false);
        textEditDOB.setEnabled(false);

        saveBtn.setEnabled(false);
        cancelBtn.setEnabled(false);
    }

    class ButtonListener implements ActionListener {

        public void actionPerformed(ActionEvent a) {

            JButton b = (JButton) a.getSource();
            String pressedBtn = b.getText();

            // if the Edit button has been clicked
            if (pressedBtn.equals("Edit")) {

                textEditName.setText(textName.getText());
                textEditAge.setText(textAge.getText());
                textEditDOB.setText(textDOB.getText());

                textEditName.setEnabled(true);
                textEditAge.setEnabled(true);
                textEditDOB.setEnabled(true);

                saveBtn.setEnabled(true);
                cancelBtn.setEnabled(true);

            } else if (pressedBtn.equals("Save")) { // if the Save button has been clicked

                int reply = JOptionPane.showConfirmDialog(null, "Are you sure you want to save?", "Save", JOptionPane.YES_NO_OPTION);

                if (reply == JOptionPane.YES_OPTION) {

                    updateXML();
                }

            } else { // else the Cancel button has been clicked

                nullEdit();
            }
        }
    }

    public void updateXML(){

        // for each user in the node list, find an ID match
        for (int i = 0; i < listOfUsers.getLength(); i++) {

            Element el = (Element) listOfUsers.item(i);
            String strId = el.getAttribute("id");

            // if an ID match has been found, update the component's details
            if (objID.equals(strId)) {

                try {

                    String strName = textEditName.getText();
                    String strAge = textEditAge.getText();
                    String strDOB = textEditDOB.getText();

                    DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
                    DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
                    Document doc = docBuilder.parse(new File(fileSource));

                    doc.getElementsByTagName("name").item(i).setTextContent(strName);
                    doc.getElementsByTagName("age").item(i).setTextContent(strAge);
                    doc.getElementsByTagName("dob").item(i).setTextContent(strDOB);

                    TransformerFactory transformerFactory = TransformerFactory.newInstance();
                    Transformer transformer = transformerFactory.newTransformer();
                    DOMSource domSource = new DOMSource(doc);
                    StreamResult streamResult = new StreamResult(new File(fileSource));

                    transformer.transform(domSource, streamResult);

                    el.getElementsByTagName("name").item(i).setTextContent(strName);
                    el.getElementsByTagName("age").item(i).setTextContent(strAge);
                    el.getElementsByTagName("dob").item(i).setTextContent(strDOB);

                    textName.setText(strName);
                    textAge.setText(strAge);
                    textDOB.setText(strDOB);
                    editBtn.setEnabled(true);

                    break;

                } catch (Exception e) {

                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {

        SwingUtilities.invokeLater(new Runnable() {

            public void run() {

                DomainModel dm = new DomainModel();
                dm.setVisible(true);
            }
        });
    }
}

我现在正在实现一些附加功能,并且我坚持将 DOM 与“持久层”分开。我已尝试对此进行进一步研究,但是对于要做什么或它是什么,我仍然有些模糊。

非常感谢。

【问题讨论】:

  • google for Model-View-Controller 设计模式和类似方法 - 简而言之,您应该将代码分成几层。持久层应该在内部处理数据操作,并有一些可以从 UI 调用的接口。表示层应该分开,它应该只包含创建控件和从持久性接口调用方法的简单代码片段。
  • 感谢您的及时回复。我熟悉 MVC 方法,所以在这种情况下,createTree() 方法是否会归类在 Model 下?这有点令人困惑,因为我还被要求演示 MVC 方法;所以从技术上讲,它们都是一样的。再次,非常感谢。
  • 其实等等...它显示在UI上,所以它可能是View。但话又说回来,它需要使用 XML 文件中的数据才能显示它,因此它可能被归类为控制器。
  • 文件操作(读/写)是你的模型;创建控件是您的视图;将数据从模型到视图是你的控制器
  • 所以我认为 createTree() 将属于 Controller,因为它必须从 XML 文件(模型)中收集数据才能将其显示在应用程序的 UI(视图)上。

标签: java persistence layer jtree


【解决方案1】:

我正在从 cmets 切换到答案,因为我需要在这里进行格式化 ;)

首先,这个 createTree 方法应该被拆分成更小的部分,因为它实际上混合了所有层。控制器不应该关心你有什么 UI 控件,也不应该关心它使用什么样的数据存储。想象一下这样的伪解码:

interface DataStore { // model
    List<User> getUsers();
    void saveNewUser(User user);
}
class XmlDataStoreImpl implements DataStore { ... }
interface Ui { // view
    void showUsers(List<User> users);
    User getUserDataFromControls();
}
class DomainModel extends JFrame implements Ui { // view
    static void main(String[] args) {
        DataStore dataStore = new XmlDataStoreImpl("users.xml");
        AppController app = new AppController(dataStore, this);
        app.loadUsers();
    }
    void init() {
        createControls(); // create empty JTree object and other controlls
    }
}
class AppController { // controller
    DataStore dataStore;
    Ui ui;
    public AppController(DataStore ds, Ui ui) { 
        ... 
        ui.init();
    }
    void loadUsers() {
        ui.showUsers(dataStore.getUsers()); // this line is your "createTree" but independent on implementations of model and view
    }
    void saveButtonClickedHandler() {
        User user = ui.getUserDataFromControls();
        dataStore.saveNewUser(user);
    }
}

【讨论】:

  • 感谢您的及时回复,也很抱歉打扰 cmets XP
  • 我一直在尝试我自己的版本,目前还没有完全发挥作用。我创建了一个名为 User 的类来创建用户对象,一个名为 UserHandler 的处理程序形成了用于创建用户对象并将它们添加到列表中的蓝图,只需要使用 XML 文件来调用来引用,我已经创建了一个扩展名为 GUI 的 JFrame 类,它所做的只是形成应用程序的 UI 结构。
【解决方案2】:

感谢Kamil Mikolajczyk,我能够使用Java 研究MVC,并通过this link 找到了一个非常好的示例。

再次感谢您的帮助Kamil Mikolajczyk

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多