在java中的字段中存储方法(干净地)

问题描述 投票:0回答:1

我的情况是尽可能干净地使用Javas OOP设计我的游戏,我需要将另一个类的静态方法存储到当前的字段中,而不使用

try{}catch{}
。更具体地说,我需要具有多个具有多个可排序类的排序方法,如下所示:

//For storing all legal types of sorting
public enum SortType {
    ByPositionX,
    ByPositionY,
    ByPositionZ,
    ByPosition2d,
    //...
}

并非所有可排序的类都必须包含所有方法,因此:

//for classes to sort
public interface Sortable {
    boolean supportsSortType(SortType type);
    double getSortValue(SortType type, double... args);
}

然后我想起了 DRY 并执行了一整套新的排序函数:

public class Sorting {

    //as you can see all the functions has the same return type and args
    public static double getSortValueByPositionX(Object position, double... args) {
        return (Point)(position).getX();
    }

    public static double getSortValueByPositionY(Object position, double... args) {
        return (Point)(position).getY();
    }

    public static double getSortValueByPositionZ(Object position, double... args) {
        return (Point)(position).getZ();
    }
    
    public static double getSortValueByPosition2d(Object position, double... args) {
        double width = args[0];
        return (Point)(position).getX() + position.getY() * width;
    }
    
    //may it work???
    @FunctionalInterface
    public interface SortingValueMethod {
        double getSortValue(Object field, double... args);
    }
}

为了方便存储,我用相同的布局完成了所有功能,现在我遇到了问题:

public class Block implements Sortable {

    //it actually has to be public static final Map<SortType, Method>
    public static final SortType[] SUPPORTED_SORT_TYPES = {
        SortType.ByPositionX,
        SortType.ByPositionY,
        SortType.ByPositionZ,
        SortType.ByPosition2d,
    };

    @Override
    public boolean supportsSortType(SortType type) {
        for (SortType curSortType : SUPPORTED_SORT_TYPES)
            if (curSortType.equals(type))
                return true;
                
        return false;
    }

    @Override
    public double getSortValue(SortType type, double... args) throws UnsupportedSortTypeException {
        if (!supportsSortType(type))
            throw new UnsupportedSortTypeException("Type " + type.toString() + " is unsupported for class " + Block.class.getName());

        
        //find a Sorting.method by a key and
        return call_it_with(this.position, null);
    }
}

我必须以某种方式将 SortTypes 和排序方法配对,出于明显的原因,我需要它作为

public static final
字段。 Java 中有什么东西可以帮助我完成这个疯狂的设计吗?

java oop reflection functional-interface
1个回答
0
投票

您似乎在询问普遍持有的面向对象原则。然而,您的代码与任何能够满足绝大多数此类原则的要求相去甚远。 //for classes to sort public interface Sortable { boolean supportsSortType(SortType type); double getSortValue(SortType type, double... args); }

不;这违反了里氏替换原则。以“静态”方式抛出一个 
UnsupportedOperationException

(给定的对象,或者更糟糕的是,给定类的任何实例,对于给定的方法都会

always
抛出它),是一个相当大的代码味道。如果你的类实现了 Sortable,并且 Sortable 暗示你支持 getSortValue(SortType.ByPositionX, args),我希望你的类型支持它。我不想看到这种方法:“Psyche!!我实际上并不支持哈哈!”。
如果按所有这 4 个不同维度进行排序很重要,则有 4 个不同的接口。

请注意,关于如何编程有多种“准则”(DRY 是其中之一;Liskov 是另一条)。各种情况都会导致冲突:全力以赴地遵循一个“原则”会导致严重违反另一个“原则”。编程就是对这些格言的简单死记硬背,直到你将它们全部应用为止。事情比这复杂得多。良好的 API 和良好的代码设计(从某种意义上说,它易于理解、易于修改、面对变更请求时稳健、易于测试,并且错误(如果存在)很容易发现/容易根据失败的单元测试找出问题所在)是

很多

更复杂! 您可能想阅读方法引用/lambda。您可以将代码存储在变量中(我过于简单化了):

Comparator<Point> orderByX = Comparator.comparingDouble(Point::getX);

上面为您提供了一个可以比较任意 2 个点的比较器对象,并通过比较每个点返回的“x”值来实现这一点。然后,您可以对 Point 实例列表进行排序:
list.sort(orderByX)

您可以“捕捉”“我只需要您将任何 T 转换为代表其排序顺序的双精度值,我将处理其余的”的想法,例如,

java.util.function.ToDoubleFunction<T>

Point::getX
是它的一种实现:
ToDoubleFunction<T> func = Point::getX;

(当然假设那是
public class Point { public double getX() { ... }}

)。

这不会在 Point 上调用 getX(你不能;Point 是一个类,而不是实例),它捕获了在 Point 的某个实例上调用 getX 的

idea

。您可以根据需要多次调用 func.apply(somePointInstance),使用您能找到的任何 Point 实例来获得双打。

看一下 Comparator 类,它包含大量静态方法,这些方法将此类方法引用或 lambda 转换为比较器,这就是您真正要寻找的(不要重新发明排序轮,java 已经有了它,而且它是称为 

java.util.Comparator

)。

    

© www.soinside.com 2019 - 2024. All rights reserved.