如果唯一的区别是 for 循环中的方法调用,请避免重复代码
Avoid duplicated code if the only diffence is a method call in a for loop
我把这两个方法写在java:
public void fillRect(float x, float y, float width, float height, Color color) {
int xi = mapX(x);
int yi = mapY(y);
int heightf = mapHeight(height);
int widthf = mapWidth(width);
if (xi + widthf > pixelWidth){
widthf -= xi + widthf - pixelWidth;
}
if (yi + heightf > pixelHeight){
heightf -= yi + heightf - pixelHeight;
}
if (xi < 0) {
widthf += xi;
xi = 0;
}
if (yi < 0) {
heightf += yi;
yi = 0;
}
for (int xx = xi; xx < xi + widthf; xx++){
for (int yy = yi; yy < yi + heightf; yy++){
// here is the difference between the other method
setPixel(xx,yy,color);
}
}
}
public void fillRect(float x, float y, float width, float height,float transparency, Color color) {
int xi = mapX(x);
int yi = mapY(y);
int heightf = mapHeight(height);
int widthf = mapWidth(width);
if (xi + widthf > pixelWidth){
widthf -= xi + widthf - pixelWidth;
}
if (yi + heightf > pixelHeight){
heightf -= yi + heightf - pixelHeight;
}
if (xi < 0) {
widthf += xi;
xi = 0;
}
if (yi < 0) {
heightf += yi;
yi = 0;
}
for (int xx = xi; xx < xi + widthf; xx++){
for (int yy = yi; yy < yi + heightf; yy++) {
// here is the difference between the other method
// this Method is slower then setPixel()
plot(xx,yy,transparency,color);
}
}
}
我习惯于编写这样的方法 validateBoundary(float* x,float* y, float* width, float *height): void 其中包括 'if-statments' 并改为调用它,但显然是这样Java 不会发生。
解决此类问题的方法是什么?我们可以编写一个 Methode validateBoundaryWidthf(xi, widhtf, pixelWitdth) ,其中 return 是 widthf 的新值。但是像这样:
if (xi < 0) {
widthf += xi;
xi = 0;
}
无法解决,因为只有一个 return 值。当然,我可以创建一个具有属性 widthf 和 xi 的 POJO 和 return this,但我认为这在 cpu / 内存方面是昂贵的。那么解决这个重复代码问题的正确方法是什么?
您可以使用消费者来处理 for
循环内的不同处理。定义一个新的功能接口,它将 xx
和 yy
值作为参数:
@FunctionalInterface
public interface PointConsumer {
void accept(int x, int y);
}
然后添加一个新方法 performOnPoints
,其中包含所有需要的参数和一个 PointConsumer
参数。它可能看起来像这样:
public void performOnPoints(float x, float y, float width,
float height, PointConsumer consumer) {
int xi = mapX(x);
int yi = mapY(y);
int heightf = mapHeight(height);
int widthf = mapWidth(width);
if (xi + widthf > pixelWidth){
widthf -= xi + widthf - pixelWidth;
}
if (yi + heightf > pixelHeight){
heightf -= yi + heightf - pixelHeight;
}
if (xi < 0) {
widthf += xi;
xi = 0;
}
if (yi < 0) {
heightf += yi;
yi = 0;
}
for (int xx = xi; xx < xi + widthf; xx++){
for (int yy = yi; yy < yi + heightf; yy++){
consumer.accept(xx, yy);
}
}
}
然后您可以像这样重写现有的 fillRect
方法:
public void fillRect(float x, float y, float width, float height, Color color) {
performOnPoints(x, y, width, height, (xx, yy) -> setPixel(xx, yy, color));
}
public void fillRect(float x, float y, float width, float height,
float transparency, Color color) {
performOnPoints(x, y, width, height, (xx, yy) -> plot(xx,yy,transparency,color);
}
如您所见,它们都对所有特殊 if()
语句使用相同的循环代码,但您只有一次此代码。对于不同的参数,您将使用不同的消费者对象,一个调用 setPixel()
,另一个调用 plot()
.
您可以定义 public void fillRect(bool plot, float x, float y, float width, float height,float transparency, Color color)
,其中 plot
指示应使用哪个实现。当 false 时使用第一个选项。当 true 时使用第二个选项。
我把这两个方法写在java:
public void fillRect(float x, float y, float width, float height, Color color) {
int xi = mapX(x);
int yi = mapY(y);
int heightf = mapHeight(height);
int widthf = mapWidth(width);
if (xi + widthf > pixelWidth){
widthf -= xi + widthf - pixelWidth;
}
if (yi + heightf > pixelHeight){
heightf -= yi + heightf - pixelHeight;
}
if (xi < 0) {
widthf += xi;
xi = 0;
}
if (yi < 0) {
heightf += yi;
yi = 0;
}
for (int xx = xi; xx < xi + widthf; xx++){
for (int yy = yi; yy < yi + heightf; yy++){
// here is the difference between the other method
setPixel(xx,yy,color);
}
}
}
public void fillRect(float x, float y, float width, float height,float transparency, Color color) {
int xi = mapX(x);
int yi = mapY(y);
int heightf = mapHeight(height);
int widthf = mapWidth(width);
if (xi + widthf > pixelWidth){
widthf -= xi + widthf - pixelWidth;
}
if (yi + heightf > pixelHeight){
heightf -= yi + heightf - pixelHeight;
}
if (xi < 0) {
widthf += xi;
xi = 0;
}
if (yi < 0) {
heightf += yi;
yi = 0;
}
for (int xx = xi; xx < xi + widthf; xx++){
for (int yy = yi; yy < yi + heightf; yy++) {
// here is the difference between the other method
// this Method is slower then setPixel()
plot(xx,yy,transparency,color);
}
}
}
我习惯于编写这样的方法 validateBoundary(float* x,float* y, float* width, float *height): void 其中包括 'if-statments' 并改为调用它,但显然是这样Java 不会发生。 解决此类问题的方法是什么?我们可以编写一个 Methode validateBoundaryWidthf(xi, widhtf, pixelWitdth) ,其中 return 是 widthf 的新值。但是像这样:
if (xi < 0) {
widthf += xi;
xi = 0;
}
无法解决,因为只有一个 return 值。当然,我可以创建一个具有属性 widthf 和 xi 的 POJO 和 return this,但我认为这在 cpu / 内存方面是昂贵的。那么解决这个重复代码问题的正确方法是什么?
您可以使用消费者来处理 for
循环内的不同处理。定义一个新的功能接口,它将 xx
和 yy
值作为参数:
@FunctionalInterface
public interface PointConsumer {
void accept(int x, int y);
}
然后添加一个新方法 performOnPoints
,其中包含所有需要的参数和一个 PointConsumer
参数。它可能看起来像这样:
public void performOnPoints(float x, float y, float width,
float height, PointConsumer consumer) {
int xi = mapX(x);
int yi = mapY(y);
int heightf = mapHeight(height);
int widthf = mapWidth(width);
if (xi + widthf > pixelWidth){
widthf -= xi + widthf - pixelWidth;
}
if (yi + heightf > pixelHeight){
heightf -= yi + heightf - pixelHeight;
}
if (xi < 0) {
widthf += xi;
xi = 0;
}
if (yi < 0) {
heightf += yi;
yi = 0;
}
for (int xx = xi; xx < xi + widthf; xx++){
for (int yy = yi; yy < yi + heightf; yy++){
consumer.accept(xx, yy);
}
}
}
然后您可以像这样重写现有的 fillRect
方法:
public void fillRect(float x, float y, float width, float height, Color color) {
performOnPoints(x, y, width, height, (xx, yy) -> setPixel(xx, yy, color));
}
public void fillRect(float x, float y, float width, float height,
float transparency, Color color) {
performOnPoints(x, y, width, height, (xx, yy) -> plot(xx,yy,transparency,color);
}
如您所见,它们都对所有特殊 if()
语句使用相同的循环代码,但您只有一次此代码。对于不同的参数,您将使用不同的消费者对象,一个调用 setPixel()
,另一个调用 plot()
.
您可以定义 public void fillRect(bool plot, float x, float y, float width, float height,float transparency, Color color)
,其中 plot
指示应使用哪个实现。当 false 时使用第一个选项。当 true 时使用第二个选项。