【问题标题】:How to maintain hardcoded values within a swing application outside the program code如何在程序代码之外的 Swing 应用程序中维护硬编码值
【发布时间】:2012-10-17 11:43:24
【问题描述】:

谁能告诉我如何分别维护所有硬编码值的设计。

我目前正在使用一些设计模式,这些可以吗?为了更好地设计我的应用程序代码,我还能做些什么。

我使用的设计模式是(我的应用程序有多个屏幕类似的向导):

  1. 对用户可见的所有字符串使用 ResourceBundle(用于国际化)
  2. 使用属性文件保存特定屏幕的所有值,以便其他屏幕可以访问(这些值用于程序内部目的,用户不可见)。我不断在程序中的各个位置加载这些属性以获取更新的值,例如,从第一个屏幕转到第二个屏幕(面板)以获取第二个屏幕中第一个屏幕的值。
  3. 我正在考虑使用资源包将日志消息外部化。

有没有更好的设计方法?与程序代码分开,A.“用户可见的消息”,B.日志消息,C.可用性值(屏幕尺寸,字体等),用户在屏幕中输入的值,目录/文件路径...

【问题讨论】:

    标签: java swing design-patterns properties internationalization


    【解决方案1】:

    我会查看Java Preferences API,,它允许您存储系统范围的默认值、每个用户的默认值,并在没有配置值的情况下使用硬编码的默认值。

    【讨论】:

      【解决方案2】:

      I18N 的资源包是完全正确的。属性文件做得很好,但如果您更改它们,您将不得不重新打包和重新部署。将其他项目放入数据库通常更灵活,因为您可以通过推送数据来更改应用程序,而无需重新打包和重新部署。

      【讨论】:

      • 我正在为 i18n 使用 ResourceBundle,这很好。另一方面,我使用属性文件来存储用户输入的输入值,但这需要在我们使用之前加载属性文件。由于内容在运行时更改,因此需要加载。是否有任何替代属性文件,以避免在许多点加载?
      • 我认为数据库可以工作,但是除了数据库方法之外,我的上述问题还有其他选择吗?
      • 属性是只读的。如果您需要在运行时进行更改,请使用数据库。
      • 何为?所以使用属性文件来编写运行时更改不是一个好方法,对吧?
      【解决方案3】:

      您的 GUI 应该有一个完整的数据模型。该模型可以读取 I18n 资源文件和常规资源文件来填充模型的一部分。数据模型是一个或多个 Java 类,在应用程序运行时保存对应用程序很重要的数据。

      例如,这是我创建的秒表 GUI。

      这是与秒表 GUI 关联的数据模型类。

      import java.util.ArrayList;
      import java.util.List;
      
      import javax.swing.table.DefaultTableModel;
      
      public class StopwatchModel {
      
          protected boolean isSplitTime;
      
          protected long startTime;
      
          protected long endTime;
      
          protected DefaultTableModel tableModel;
      
          protected List<Long> splitTimes;
      
          protected String[] columnNames = {"", "Increment", "Cumulative"};
      
          public StopwatchModel() {
              this.splitTimes = new ArrayList<Long>();
              this.isSplitTime = false;
              this.startTime = 0;
              this.endTime = 0;
              setTableModel();
          }
      
          public void resetTimes() {
              this.splitTimes.clear();
              this.isSplitTime = false;
              this.startTime = 0;
              this.endTime = 0;
          }
      
          public boolean isSplitTime() {
              return isSplitTime;
          }
      
          public long getStartTime() {
              return startTime;
          }
      
          public long getEndTime() {
              return endTime;
          }
      
          public long getLastSplitTime() {
              int size = splitTimes.size();
              if (size < 1) {
                  return getStartTime();
              } else {
                  return splitTimes.get(size - 1);
              }
          }
      
          public long getPenultimateSplitTime() {
              int size = splitTimes.size();
              if (size < 2) {
                  return getStartTime();
              } else {
                  return splitTimes.get(size - 2);
              }
          }
      
          public DefaultTableModel getTableModel() {
              return tableModel;
          }
      
          public int getTableModelRowCount() {
              return tableModel.getRowCount();
          }
      
          public void clearTableModel() {
              tableModel.setRowCount(0);
          }
      
          public int addTableModelRow(long startTime, long previousSplitTime, 
                  long currentSplitTime, int splitCount) {
              String[] row = new String[3];
      
              row[0] = "Split " + ++splitCount;
              row[1] = formatTime(previousSplitTime, currentSplitTime, false);
              row[2] = formatTime(startTime, currentSplitTime, false);
      
              tableModel.addRow(row);
      
              return splitCount;
          }
      
          public void setStartTime() {
              if (getStartTime() == 0L) {
                  this.startTime = System.currentTimeMillis();
              } else {
                  long currentTime = System.currentTimeMillis();
                  int size = splitTimes.size();
                  if (size > 0) {
                      long splitTime = splitTimes.get(size - 1);
                      splitTime = splitTime - getEndTime() + currentTime;
                      splitTimes.set(size - 1, splitTime);
                  }
                  this.startTime = currentTime - getEndTime() + getStartTime();
              }
          }
      
          protected void setTableModel() {
              this.tableModel = new DefaultTableModel();
              this.tableModel.addColumn(columnNames[0]);
              this.tableModel.addColumn(columnNames[1]);
              this.tableModel.addColumn(columnNames[2]);
          }
      
          public void setSplitTime() {
              this.splitTimes.add(System.currentTimeMillis());
              isSplitTime = true;
          }
      
          public void setEndTime() {
              Long split = System.currentTimeMillis();
              if (isSplitTime) {
                  this.splitTimes.add(split);
              }
              this.endTime = split;
          }
      
          public String formatTime(long startTime, long time, boolean isTenths) {
              long elapsedTime = time - startTime;
      
              int seconds = (int) (elapsedTime / 1000L);
      
              int fraction = (int) (elapsedTime - ((long) seconds * 1000L));
              fraction = (fraction + 5) / 10;
              if (fraction > 99) {
                  fraction = 0;
              }
              if (isTenths) {
                  fraction = (fraction + 5) / 10;
                  if (fraction > 9) {
                      fraction = 0;
                  }
              }
      
      
              int hours = seconds / 3600;
              seconds -= hours * 3600;
      
              int minutes = seconds / 60;
              seconds -= minutes * 60;
      
              StringBuilder builder = new StringBuilder();
      
              builder.append(hours);
              builder.append(":");
              if (minutes < 10) builder.append("0");
              builder.append(minutes);
              builder.append(":");
              if (seconds < 10) builder.append("0");
              builder.append(seconds);
              builder.append(".");
              if ((!isTenths) && (fraction < 10)) builder.append("0");
              builder.append(fraction);
      
              return builder.toString();
          }
      
      }
      

      该模型还包含将您从一个JPanel 带到下一个JPanel 的瞬态数据。瞬态数据是只需要在短时间内存在的数据,通常只要 GUI 处于活动状态。退出GUI后不必保存。

      您使用模型/视图来构建 GUI 的原因是关注点分离。应用程序的其余部分访问数据模型,而不是任何 GUI 组件。

      【讨论】:

      • 你能告诉我,这里的瞬态数据或数据模型到底是什么意思?
      • @merlachandra:我将您的问题的答案添加到我的答案中。
      【解决方案4】:

      对于“可用性值”,我使用了单例模式。创建一个名为 Configuration 的类,然后创建一个调用私有构造函数的静态方法 Configuration.getConfig()。您的程序需要的所有对象都可以存储为此类中的字段。构造函数使用首选项 API 加载值。我在a recent S.O. post. 中发布了一些示例代码

      将所有配置数据放在一个负责加载配置数据的类中的好处是,现在存储这些数据的方法已从其余代码中抽象出来。如果您决定使用数据库或 ResourceBundle 进行存储,则只需更改配置即可。

      【讨论】:

        猜你喜欢
        • 2016-02-28
        • 1970-01-01
        • 2023-03-17
        • 1970-01-01
        • 1970-01-01
        • 2010-09-20
        • 2018-05-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多