设计在javafx项目中保留辅助方法

时间:2016-08-06 06:34:44

标签: java design-patterns javafx java-8

这可能更多的是设计选择,我想"为什么重新发明轮子"。有人可能已经要求这样做了。

(我不想去任何第三方框架,因为我的是一个小项目。我正在使用Adam Bein afterburner.fx。我正在javafx中实现一个独立的应用程序。我对跟随MVC / MVP / MVVM非常感兴趣。由于javafx允许我使用fxml分离UI,因此我通过fxml完成​​了大部分UI设计。但是我遇到了一些问题。

我的结构

  • TradeView.fxml(我所有的UI设计都在这里)
  • TradeController(我的所有UI事件处理(也是一些业务逻辑)都在这里)
  • Trade(实体类)

现在我的TableView中有一个JavaFX fxml。所有TableColumn都在fxml本身中定义。我希望绑定到我的列的值是通过PropertyValueFactory实现的,如果它是我的实体类中的直接属性。

TableView<Trade> myTableView;

例如:

<TableColumn fx:id="tradeOidTableColumn" prefWidth="130.0" text="Trade Oid">
    <cellValueFactory><PropertyValueFactory property="oid"/></cellValueFactory>
</TableColumn>

但我希望在一列中显示商品短名称,其中Commodity是与我的Trade实体关系的另一个实体。所以我可以使用

myTradeEntity.commodity().commodityShortName();

获取值,完美无缺。但你们知道我不能这样做fxml。它不支持嵌套绑定。

不可能

<cellValueFactory><PropertyValueFactory property="commodity.commodityShortName"/></cellValueFactory>

所以我被迫使用单元值工厂。我定义了一个类CommodityCellValueFactory并绑定它。 例如:

<TableColumn fx:id="commodityTableColumn" prefWidth="220.0" text="Commodity">
    <cellValueFactory><CommodityCellValueFactory /></cellValueFactory>
</TableColumn>  

基本上我想摆脱细胞工厂和细胞价值工厂,除非我需要对我的价值进行一些格式化。所以我想我可以创建一个名为

的属性
String tempCommodityShortName;
String getTempCommodityShortName()
{
    return commodity.commodityShortName();
}
在我的Trade实体中

并将其绑定到我的表列。但我有15到20个属性。如果我在我的实体类中执行此操作,那么使用这些我不想做的额外帮助方法会使它变得臃肿。

我想为TradeEntityHelper / TradeEntityBusiness / TradeEntityAdditions这样的每个实体都有一个帮助器类,我可以使用所有帮助器方法并在tableview列中访问它。

我的第一次尝试是代替类,我选择了一个接口(因为java 8接口支持默认方法)

interface ITradeEntityHelper
{
//all helper methods goes here
}

class TradeEntity implements ITradeEntityHelper
{
//real entity methods goes here
}

我会将界面绑定到我的TableViewTableView<ITradeEntityHelper>代替TableView<TradeEntity>如果我正在尝试愚蠢的事情,请纠正我

现在问题是如何在我的TradeEntity界面中获取ITradeEntityHelper引用,以便我可以询问

tradeEntity.Commodity().commodityShortName().

(或)喜欢这些

interface ITrade{}
class Trade implements ITrade{}
class TradeAdditions implements ITrade{}

将帮助器方法保留在Additions类中。

我也想为我的Controller类实现相同的功能。

例如:
我的Application中的每个Controller类都应该有基本接口,我希望在其中定义一些默认的java Predicate和java 8 Function,并希望在控制器类中重新生成。

class TradeController implements ITradeController, Initializable
{
}

1 个答案:

答案 0 :(得分:0)

您可以使用{{3}}通过多级层次结构选择值。这允许您创建一个cellValueFactory类:

import java.util.Arrays;
import javafx.beans.NamedArg;
import javafx.beans.binding.Bindings;
import javafx.beans.value.ObservableValue;
import javafx.scene.control.TableColumn;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.util.Callback;

public class NestedPropertyValueFactory<S, T> implements Callback<TableColumn.CellDataFeatures<S, T>, ObservableValue<T>> {

    private final String[] steps;
    private final PropertyValueFactory firstStepSelector;

    /**
     * @param property a string containing the names of the properties seperated
     * by '.'.
     */
    public NestedPropertyValueFactory(@NamedArg("property") String property) {
        String[] properties = property.split("\\.");
        firstStepSelector = new PropertyValueFactory<>(properties[0]);
        this.steps = Arrays.copyOfRange(properties, 1, properties.length);
    }

    @Override
    public ObservableValue<T> call(TableColumn.CellDataFeatures<S, T> param) {
        // use PropertyValueFactory for first step and Bindings.select for
        // additonal steps.
        return Bindings.select(firstStepSelector.call(param), steps);
    }

}

此类可用作fxml文件中的cellValueFactory

<cellValueFactory>
    <NestedPropertyValueFactory property="commodity.commodityShortName"/>
</cellValueFactory>

请注意,如果任何中间步骤产生null,您将在System.err中收到警告。

同样使用此类,您需要使用符合命名约定的属性方法,即在这种情况下方法的名称应为commodityPropertycommodityShortNameProperty(或getCommodity和{ {1}}它们是不可观察的。)