如何更好地设计此代码和逻辑

时间:2013-07-10 18:36:13

标签: grails architecture groovy

Request类的属性colorType可以是不同的颜色。根据颜色的类型,它将涉及不同的处理方式。

这是控制器代码:

def colorInstance = Color(params)
//validates and checks the params. Also, based on some logic sets the `colorType` property 
//to be appropriate color
if (colorInstnace.validate()) 
{
   colorService.processColor(colorInstance)
}

以下是colorService代码:

void processColor(Color colorInstance) { 
  if (colorInstance.colorType == "green")
      processGreen(colorInstance)
  else if (colorInstance.colorType == "red")
      processRed(colorInstance)
  ....
  ......
}

processGreen(Color colorInstance) {
  //common code
  //code specific to colortypes that are GREEN
  //more common code
}

processRed(Color colorInstance) { 
  //common code
  //code specific to colortypes that are RED
  //more common code
}

问题

  1. 如何更改服务中的代码,以便我不必复制粘贴所有processXXX方法中的代码?
  2. 如何消除if/elseif方法中的processColor

3 个答案:

答案 0 :(得分:1)

我认为如果你使用整数常量会更容易......例如

// you could use actual RGB too.. then red would be 0xff0000
static final int RED = 0
static final int BLUE = 1
static final int GREEN = 2

然后在colorService中,您可以尝试这样的事情......

void processColor(Color colorInstance) { 
  commonMethodOne();

  switch(colorInstance.colorType){

  case RED:
     //Handle the red color
  case BLUE:
    // Handle the blue color, etc.

  }

  commonMethodTwo();
}

commonMethodOne(){
  //Here is code that gets executed regardless of Color
}

commonMethodTwo(){
  //Here is more code that gets executed regardless of Color
}

答案 1 :(得分:1)

服务类可以具有以下实现。

void processColor(Color colorInstance) { 
  processCommonCodeBefore(colorInstance)
  processColorSpecificCode(colorInstance)
  processCommonCodeAfter(colorInstance)      
}

processCommonCodeBefore(Color colorInstance) {
  //common code
}

processCommonCodeAfter(Color colorInstance) { 
  //common code
}

processColorSpecificCode(Color colorInstance) { 
     switch(colorInstance.colorType){
        case 'green':
            processGreen(colorInstance)
            break
        case 'blue':
            processBlue(colorInstance)
            break
        default:
            processDefault(colorInstance)
     }      
}

这样,服务类内的所有方法都可以有效地进行单元测试。

答案 2 :(得分:1)

即使答案已被接受,我也想指出使用enum ColorType的替代解决方案。

class Color {
    ColorType colorType
    ...
}

enum ColorType {
    blue {
        @Override void process(Color color) {
            // code for processing blue
        }
    },
    green {
        @Override void process(Color color) {
            // code for processing green
        }
    },
    red,
    yellow

    void process(Color color) {
        // used for red and yellow
    }
}

与java一样,您可以在枚举中添加方法(如process(Color color))。您还可以为某些枚举常量覆盖这些方法。在此示例中,枚举值bluegreen会覆盖process(Color color)方法。

使用这种方法你可以做到这一点:

void processColor(Color colorInstance) {
     commonMethod(colorInstance)
     colorInstance.colorType.process(colorInstance)
     otherCommonMethod(colorInstance)
}

这个例子的问题是它在ColorColorType之间创建了一个循环依赖,应该避免。但是,根据您的实现,可能会从color方法中删除ColorType.process()参数来解决此问题。

我只是想指出,对于这种情况,重写枚举方法有时可能是一个有用的功能: - )