java - 使用重载的方法重复
问题描述
我如何重构“方法”以便不重复代码?对于暂停、恢复和停止,它基本上做同样的事情。目前我正在使用布尔重载的方法,所以不是最好的主意。我不知道要搜索什么,所以给我一些提示
private static void method(final boolean pause, final boolean resume, final boolean stop) {
planes.forEach(plane -> {
if (pause) {
if (plane.getPlaneMovementAnimation() != null) {
plane.getPlaneMovementAnimation().pause();
}
if (plane.getLandingAnimation() != null) {
plane.getLandingAnimation().pause();
}
if (plane.getRandomTransition() != null) {
plane.getRandomTransition().pause();
}
} else if (resume) {
if (plane.getPlaneMovementAnimation() != null && plane.getStatusMovementAnimation().equals("PAUSED")) {
plane.getPlaneMovementAnimation().play();
}
if (plane.getLandingAnimation() != null && plane.getStatusMovementAnimation().equals("PAUSED")) {
plane.getLandingAnimation().play();
}
if (plane.getRandomTransition() != null && plane.getStatusMovementAnimation().equals("PAUSED")) {
plane.getRandomTransition().play();
}
} else if (stop) {
if (plane.getPlaneMovementAnimation() != null) {
plane.getPlaneMovementAnimation().stop();
}
if (plane.getLandingAnimation() != null) {
plane.getLandingAnimation().stop();
}
if (plane.getRandomTransition() != null) {
plane.getRandomTransition().stop();
}
}
});
}
public static void pause() {
method(true, false, false);
}
public static void resume() {
method(false, true, false);
}
public static void stop() {
method(false, false, true);
}
解决方案
我认为使用每个命令在其自己的单独方法中的逻辑,这将更具可读性。现在的编写方式,方法中的所有内容都命名为method
,使得更难理解每个命令的逻辑,同时没有删除太多重复(仅planes.foreach
部分)。也可以以没有意义的方式调用它,例如传递多个true
参数。因此,作为多步骤重构过程的第一步,我会将逻辑提取回各个方法中:
public static void pause() {
planes.forEach(plane -> {
if (plane.getPlaneMovementAnimation() != null) {
plane.getPlaneMovementAnimation().pause();
}
if (plane.getLandingAnimation() != null) {
plane.getLandingAnimation().pause();
}
if (plane.getRandomTransition() != null) {
plane.getRandomTransition().pause();
}
});
}
public static void resume() {
planes.forEach(plane -> {
if (plane.getPlaneMovementAnimation() != null && plane.getStatusMovementAnimation().equals("PAUSED")) {
plane.getPlaneMovementAnimation().play();
}
if (plane.getLandingAnimation() != null && plane.getStatusMovementAnimation().equals("PAUSED")) {
plane.getLandingAnimation().play();
}
if (plane.getRandomTransition() != null && plane.getStatusMovementAnimation().equals("PAUSED")) {
plane.getRandomTransition().play();
}
});
}
public static void stop() {
planes.forEach(plane -> {
if (plane.getPlaneMovementAnimation() != null) {
plane.getPlaneMovementAnimation().stop();
}
if (plane.getLandingAnimation() != null) {
plane.getLandingAnimation().stop();
}
if (plane.getRandomTransition() != null) {
plane.getRandomTransition().stop();
}
});
}
接下来,如果Plane
能够更改类,我将在该类中封装每个命令的逻辑。这样,调用者就不需要知道飞机每个动画的内部细节:
public static void pause() {
planes.forEach(Plane::pause);
}
public static void resume() {
planes.forEach(Plane::resume);
}
public static void stop() {
planes.forEach(Plane::stop);
}
class Plane {
public void pause() {
if (getPlaneMovementAnimation() != null) {
getPlaneMovementAnimation().pause();
}
if (getLandingAnimation() != null) {
getLandingAnimation().pause();
}
if (getRandomTransition() != null) {
getRandomTransition().pause();
}
}
public void resume() {
if (getPlaneMovementAnimation() != null && getStatusMovementAnimation().equals("PAUSED")) {
getPlaneMovementAnimation().play();
}
if (getLandingAnimation() != null && getStatusMovementAnimation().equals("PAUSED")) {
getLandingAnimation().play();
}
if (getRandomTransition() != null && getStatusMovementAnimation().equals("PAUSED")) {
getRandomTransition().play();
}
}
public void stop() {
if (getPlaneMovementAnimation() != null) {
getPlaneMovementAnimation().stop();
}
if (getLandingAnimation() != null) {
getLandingAnimation().stop();
}
if (getRandomTransition() != null) {
getRandomTransition().stop();
}
}
// ...
}
如果您不熟悉语法,Plane::pause
其他类似的语法是 lambda 表达式的快捷方式,称为方法引用。Plane::pause
与 相同plane -> plane.pause()
。
当然,这只会将重复项移入Plane
,所以让我们继续。该方法的结构与其他resume
方法略有不同,因为它检查getStatusMovementAnimation().equals("PAUSED")
每个if
语句。我们可以将该检查提取到外部if
,因为每个检查都是相同的:
public void resume() {
if (getStatusMovementAnimation().equals("PAUSED")) {
if (getPlaneMovementAnimation() != null) {
getPlaneMovementAnimation().play();
}
if (getLandingAnimation() != null) {
getLandingAnimation().play();
}
if (getRandomTransition() != null) {
getRandomTransition().play();
}
}
}
现在每种方法的结构几乎相同。假设getPlaneMovementAnimation()
、getLandingAnimation()
和getRandomTransition()
都返回相同的类型(我称之为Animation
),我们可以提取一个方法,该方法返回null
飞机的非动画集合:
class Plane {
private Collection<Animation> getActiveAnimations() {
Collection<Animation> activeAnimations = new HashSet<>();
if (getPlaneMovementAnimation() != null) {
activeAnimations.add(getPlaneMovementAnimation());
}
if (getLandingAnimation() != null) {
activeAnimations.add(getLandingAnimation());
}
if (getRandomTransition() != null) {
activeAnimations.add(getRandomTransition());
}
return Collections.unmodifiableCollection(activeAnimations);
}
public void pause() {
getActiveAnimations().forEach(Animation::pause);
}
public void resume() {
if (getStatusMovementAnimation().equals("PAUSED")) {
getActiveAnimations().forEach(Animation::play);
}
}
public void stop() {
getActiveAnimations().forEach(Animation::stop);
}
现在,几乎没有任何重复。只有getActiveAnimations().forEach
andplanes.forEach
调用。就个人而言,我认为不值得尝试删除这种重复,因为它只是每个地方的一个电话。但是,如果你真的想要,你可以提取forEachPlane
和forEachAnimation
这样的方法:
private static void forEachPlane(Consumer<Plane> action) {
planes.forEach(action);
}
推荐阅读
- php - Docker(Mac)php异常后没有反应
- powershell - Powershell - F5 iRules -- 提取 iRules
- google-kubernetes-engine - 使用自定义服务帐户从 GKE 中拉取 GCR 中的 Docker 映像
- c++ - 编辑单个 YAML 值而不更新 YAML 其余部分的格式(YAML CPP)
- angular - 如何在 NestJS 中管理 Strategy 用户信息并在 Angular 中将其传递给客户端?
- sql - Amazon RDS - Postgres 不使用 SELECT 查询的索引
- swift - 替代案例 Swift
- flutter - 如何转换列表
Dart 中的字符串 - mysql - 在mysql数据库的所有表中搜索
- ios13 - 在 iOS13 上读取 ISO 15693 标签