dongnuo3749 2017-04-24 04:26
浏览 31

克服Go中复杂设计中的界面限制

I want to set an interface that enforces the following behavior. Structs that implement the Rules interface, implement a prepareData() function, they contain Conditions that Evaluate() the prepared data, and return a result. If the data passes all conditions, actions can be triggered.

There may be different structs that implement this Rules interface e.g. a JSONRules object as in the example below, where the prepared data are in JSON format, and a JSON Condition that simply checks for a value of a field in the JSON object. Or it could be something completely different e.g. GET a URL and check if it is reachable with HTTP status is 200.

There's 3 objectives in the design:

  1. The main program should be agnostic to the implementation e.g. whether it's JSONRules or a URLRules that it's executing. It should simply be able to say Do(Rules) e.g. do what you have to do and let me know the result.

  2. The sequence of execution e.g. prepareData(), evaluateConditions() should be abstracted since it is the same for all Rules and we shouldn't have to write it all over again.

  3. As part of the sequence of execution, actions will be triggered via a separate, specialized component which could be an external API, which is one more reason that this part should be abstracted and not re-implemented by each individual rules.

Below is an example of how I went about implementing this. The problem that I face is that the Data and the way the data are evaluated by each Condition are different for every implementation, which means that the Condition interface cannot be aware of certain fields or functions, but yet, the implementations need to follow the interfaces. I therefore get a "data.actualValue undefined (type Data is interface with no methods)" error in the following example.

The code should speak for itself, if I'm not explaining this well. Are there are any design pattern in Go that would help overcoming the limitations in interfaces in Go?

Here is a link to the code at the Go Playground: https://play.golang.org/p/G9XnEZ74bM

package main

import (
  "fmt"
)

func main() {
  condition := JSONCondition{ "Expected Value" }
  rules := JSONRules{
    RulesBase{
      data : nil,
      conditions : []Condition{ condition },
    },
  }                                                                                                                                                                                                                         
  Do(rules)
}

type Rules interface {
  getData() Data
  getConditions() []Condition
  prepareData()
  evaluateConditions() bool
}

type RulesBase struct {
  data         Data
  conditions []Condition
}

func (rules RulesBase) getData() Data {
  return rules.data
}

func (rules RulesBase) getConditions() []Condition {
  return rules.conditions
}

func (rules RulesBase) evaluateConditions() bool {
  allOk := true
  for _, condition := range rules.getConditions() {
    ok := condition.Evaluate(rules.getData())
    if !ok {
      allOk = false
      break
    }
  }  

  return allOk
}

func Do(rules Rules) {
  rules.prepareData()
  ok := rules.evaluateConditions()

  if ok {
    // Take some actions if the conditions evaluated successfully.                                                                                                                                                                           
    fmt.Println("Conditions passed.")
  }
}

type Data interface {}

type Condition interface {
  Evaluate(Data) bool
}

type JSONRules struct {
  RulesBase
  // Could have additional fields that would be used to prepare the data such as                                                                                                                                                             
  // a URL to fetch data from in the prepareData() function.                                                                                                                                                                                 
}

func (rules JSONRules) prepareData() {
  rules.data = JSONData {
    actualValue : "Expected Value",
  }
}

type JSONData struct {
  actualValue string
}

type JSONCondition struct {
  expectedValue string
}

func (condition JSONCondition) Evaluate(data Data) bool {
  if data.actualValue == condition.expectedValue {
    return true
  }

  return false
}
  • 写回答

0条回答 默认 最新

    报告相同问题?

    悬赏问题

    • ¥15 基于卷积神经网络的声纹识别
    • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
    • ¥100 为什么这个恒流源电路不能恒流?
    • ¥15 有偿求跨组件数据流路径图
    • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
    • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
    • ¥15 CSAPPattacklab
    • ¥15 一直显示正在等待HID—ISP
    • ¥15 Python turtle 画图
    • ¥15 stm32开发clion时遇到的编译问题