Higher-order functions implement object-oriented behavior patterns

Abstract To:  Starting from Java 's traditional design patterns , compare Scala 's implementation of functional programming.

Keywords: design patterns; Java ; Scala

0 Behavior mode

Behavioral mode is used to describe the complex process control of the program at runtime, that is, how multiple classes or objects cooperate to complete tasks that a single object cannot complete alone. It involves the allocation of responsibilities between algorithms and objects.

Behavioral models are divided into class behavioral models and object behavioral models. The former uses inheritance mechanisms to assign behaviors among classes, and the latter uses combination or aggregation to distribute behaviors among objects. Because the combination relationship or the aggregation relationship is less coupled than the inheritance relationship and satisfies the "synthetic reuse principle", the object behavior model has greater flexibility than the class behavior model.

1 Strategy mode and template mode

  Strategy mode, as the name implies, is the behavioral strategy of the class, or the strategy of using different algorithms. The general understanding is to choose different strategies as the situation changes. Compared with the branch implementation of hard-coded (multiple conditional transition statements), the strategy mode conforms to the principle of opening and closing.

      The strategy mode is mainly composed of three parts: strategy interface (Strategy), concrete strategy (Concrete Strategy), and strategy environment (Context). as the picture shows.

The template method pattern refers to a process in which a function is given in advance, and the logic in the specific process is implemented by subclasses.

2 Small MVC framework

      The following will use a small MVC Web architecture, in which the View part can be implemented in the strategy mode. The architecture is shown in the figure.

 

3 Java code implementation

3.1 Strategy mode

 

/**

 * 用于生成响应体(HttpResponse.body)的接口

 */

public interface View {

    String render(Map<String, List<String>> model);

}
/**

 * 策略接口

 */

public interface RenderingStrategy {

    public String renderView(Map<String, List<String>> model);

}

 

/**

 * 策略模式下的Context类,用于组合不同的策略

 */

public class StrategyView implements View {

    /**

     * 策略提供的实例

     */

    private RenderingStrategy renderingStrategy;



    public StrategyView(RenderingStrategy renderingStrategy){

        this.renderingStrategy=renderingStrategy;

    }



    /**

     * 使用策略来渲染View

     *

     * @param model

     * @return

     */

    @Override

    public String render(Map<String, List<String>> model) {

        return renderingStrategy.renderView(model);

    }

}

 

      We only need to implement the RenderingStrategy interface, and then use different implementation classes to instantiate the StrategyView class to use different strategies. Of course, you can also give the method of adjusting the strategy in StrategyView , which will increase the flexibility of the code.

 

4 Implementation of Scala code

4.1 Strategy Mode

      View remains unchanged and the code is as follows:

trait View {

  def render(model:Map[String,List[String]]):String

}

     Strategy makes the following changes:

/**

 * 用高阶函数来实现函数式接口

 * renderingStrategy现在是一个函数变量,用var修饰时,会生成get和set方法,方便动态修改策略。

 * 这样,对比于面向对象的接口实现策略,函数式策略更加简单。

 * @param renderingStrategy

 */

class StrategyView(var renderingStrategy: Map[String,List[String]] => String) extends View {



  override def render(model: Map[String, List[String]]): String = {

    renderingStrategy(model)

  }

}

   This is equivalent to a change to the functional interface. The strategy interface is the behavior of the object, that is, a combination of single or multiple functions, so that the strategy interface can be implemented through a function variable.

4.2 The template method pattern implements Controller

/**
 * 控制器接口
 * 包含了对HttpRequest的基本处理逻辑
 */
trait Controller {
    /**
     * 处理request,返回response
     * @param request
     * @return
     */
    def handleRequest(request:HttpRequest):HttpResponse
}



/**
 * 模板类,用于代理特定的任务
 *
 * java实现模板模式,doRequest需要子类来继承,进而实现不同的控制器
 *
 * scala实现模板模式,用一个函数变量doRequest即可完成,不同的控制器可以由传入的不同函数来实现。
 *
 * 注意:模板方法模式采用继承来完成工作--类的行为模式,策略方法模式采用组合来完成工作--对象的行为模式
 */
class TemplateController(view: View, doRequest: HttpRequest => Map[String, List[String]]) extends Controller {
  /**
   * 处理request,返回response
   *
   * @param request
   * @return
   */
  override def handleRequest(request: HttpRequest): HttpResponse = {
      val resBuilder = HttpResponse.Builder.newBuilder()
      try {
          val model = doRequest(request)
          val body = view.render(model)
            resBuilder.body(body)
      }catch {
          case e:Exception => resBuilder.responseCode(0)
      }
      resBuilder.build()
  }
}

5 scala

6 scala calls the web framework

import tinywbe.HttpRequest
import tinywbe.framework_scala.view.StrategyView

object ExampleScala {
  def main(args: Array[String]): Unit = {
    val greetingController = new TemplateController(new StrategyView(greetingViewStrategy), doRequest)
    val controllers = Map("greetings" -> greetingController)
    val filters = List({ x: HttpRequest => println("filter" + 1); x }, { x: HttpRequest => println("filter" + 2); x }, { x: HttpRequest => println("filter" + 3); x })
    new TinyWeb(controllers, filters).handleRequest(
      HttpRequest.Builder.newBuilder()
        .body("12,12,34,56,ff,gg")
        .path("greetings")
        .build()
    ).foreach(x => println(x.getBody))
  }

  //定义控制器与模型层交互的函数
  def doRequest(request: HttpRequest): Map[String, List[String]] = {
    val path = request.getPath
    val data1 = request.getBody
    val data2 = data1.split(",").toList.map(name => s"${name} --handle")
    Map(path -> data2)
  }

  //定义View渲染的函数
  def greetingViewStrategy(model: Map[String, List[String]]) = {
    val sb = new StringBuilder
    sb.append("<h1> greeting: </h1>\n")
    model("greetings").foreach(line => sb.append(s"<h2> $line </h2>\n"))
    sb.toString
  }

}

6 Conclusion

      To put it simply, functional programming languages ​​have inherent advantages for the realization of behavioral patterns, and there is no need to maintain functional interfaces, which will greatly reduce the amount of code in the project.

      It can be concluded that for functional interfaces in object-oriented languages ​​(for example, commonly used callback interfaces), it will be more concise if the idea of ​​functional programming is introduced.

 

Guess you like

Origin blog.csdn.net/qq_33115589/article/details/114125826