流口水可执行模型

可执行模型是对引擎处理的Drools最低级别模型的重新设计。 在当前的系列(最多6.x)中,可执行模型在过去的8年中有机地增长了,从未真正成为最终用户的目标。 建议那些希望以编程方式编写规则的人通过代码生成和目标drl来完成; 这是不理想的。 从来没有任何驱动程序可以使最终用户更容易地使用它,因为在Java中广泛使用匿名类非常麻烦。 借助Java 8和Lambda的这种变化,就有可能制造出最终用户可以访问的更具吸引力的模型。

这个新模型是在高级语言的编译过程中生成的,但是也可以单独使用。 我们的目标是使该可执行模型自成一体,并避免进行进一步的字节码修改(分析,转换或生成); 从该模型的角度来看,所有内容均由代码或高级语言层提供。 例如,索引等必须由参数提供,高级语言在针对可执行模型时会通过分析生成这些参数。

它旨在利用Java 8的lambda很好地映射到Fluent级别的构建者。 这将使其对Java开发人员和语言开发人员更具吸引力。 而且,这将允许独立于任何语言的低级引擎功能设计和测试。 这意味着我们可以在引擎级别进行创新,而不必担心语言层。

可执行模型应该足够通用以映射到多个域。 这将是一个低级数据流模型,您可以在其中处理功能性反应式编程模型,但仍可用于从中构建基于规则的系统。

以下示例提供了用于构建可执行模型的流利DSL的第一个视图:

DataSource persons = sourceOf(new Person("Mark", 37),new Person("Edson", 35),new Person("Mario", 40));Variable<Person> markV = bind(typeOf(Person.class));Rule rule = rule("Print age of persons named Mark").view(input(markV, () -> persons),expr(markV, person -> person.getName().equals("Mark"))).then(on(markV).execute(mark -> System.out.println(mark.getAge()))
);

前面的代码定义了一个包含一些人员实例的数据源,并声明了人员类型的变量markV。 规则本身包含通常的两部分:LHS由传递给view()方法的一组输入和表达式定义,而RHS是由传递给then()方法的lambda表达式定义的动作。

更详细地分析LHS,语句如下:

input(markV, () -> persons)

将人员数据源中的对象绑定到markV变量,并通过对象类进行模式匹配。 从这个意义上讲,DataSource可以被视为等同于Drools入口点。

相反的表达:

expr(markV, person -> person.getName().equals("Mark"))

使用谓词定义绑定到markV变量的对象必须满足的条件才能被引擎成功匹配。 请注意,正如预期的那样,模式匹配的评估不是通过由任何种类的分析或编译过程产生的约束来执行的,而是仅通过应用实现谓词的lambda表达式来执行(在这种情况下,人员- > person.getName()。equals(“ Mark”))匹配的对象。 换句话说,前一个DSL会生成一个规则的可执行模型,该模型等效于后续drl的解析结果。

rule "Print age of persons named Mark"
whenmarkV : Person( name == "Mark" ) from entry-point "persons"
thenSystem.out.println(markV.getAge());
end

它还正在开发一个rete构建器,可以使用此DSL定义的规则。 特别是,可以将这些规则添加到CanonicalKieBase中,然后像其他任何普通KieBase一样从中创建KieSession。

CanonicalKieBase kieBase = new CanonicalKieBase();
kieBase.addRules(rule);KieSession ksession = kieBase.newKieSession();
ksession.fireAllRules();

当然,DSL还允许定义更复杂的条件,例如连接:

Variable<Person> markV = bind(typeOf(Person.class));
Variable<Person> olderV = bind(typeOf(Person.class));Rule rule = rule("Find persons older than Mark").view(input(markV, () -> persons),input(olderV, () -> persons),expr(markV, mark -> mark.getName().equals("Mark")),expr(olderV, markV, (older, mark) -> older.getAge() > mark.getAge())).then( on(olderV, markV).execute((p1, p2) -> System.out.println(p1.getName() + " is older than " + p2.getName()))
);

或存在模式:

Variable<Person> oldestV = bind(typeOf(Person.class));
Variable<Person> otherV = bind(typeOf(Person.class));Rule rule = rule("Find oldest person").view(input(oldestV, () -> persons),input(otherV, () -> persons),not(otherV, oldestV, (p1, p2) -> p1.getAge() > p2.getAge())).then( on(oldestV).execute(p -> System.out.println("Oldest person is " + p.getName()))
);

这里的not()代表所有表达式的取反,因此上面使用的形式实际上只是以下内容的快捷方式:

not( expr( otherV, oldestV, (p1, p2) -> p1.getAge() > p2.getAge() ) )

还已经以以下形式支持累计:

Variable<Person> person = bind(typeOf(Person.class));
Variable<Integer> resultSum = bind(typeOf(Integer.class));
Variable<Double> resultAvg = bind(typeOf(Double.class));Rule rule = rule("Calculate sum and avg of all persons having a name starting with M").view(input(person, () -> persons),accumulate(expr(person, p -> p.getName().startsWith("M")),sum(Person::getAge).as(resultSum),avg(Person::getAge).as(resultAvg))).then(on(resultSum, resultAvg).execute((sum, avg) -> result.value = "total = " + sum + "; average = " + avg)
);

为了提供最后一个更完整的用例,可以使用此DSL定义经典火灾和警报示例的可执行模型,如下所示。

Variable<Room> room = any(Room.class);
Variable<Fire> fire = any(Fire.class);
Variable<Sprinkler> sprinkler = any(Sprinkler.class);
Variable<Alarm> alarm = any(Alarm.class);Rule r1 = rule("When there is a fire turn on the sprinkler").view(input(fire),input(sprinkler),expr(sprinkler, s -> !s.isOn()),expr(sprinkler, fire, (s, f) -> s.getRoom().equals(f.getRoom()))).then(on(sprinkler).execute(s -> {System.out.println("Turn on the sprinkler for room " + s.getRoom().getName());s.setOn(true);}).update(sprinkler, "on")
);Rule r2 = rule("When the fire is gone turn off the sprinkler").view(input(sprinkler),expr(sprinkler, Sprinkler::isOn),input(fire),not(fire, sprinkler, (f, s) -> f.getRoom().equals(s.getRoom()))).then(on(sprinkler).execute(s -> {System.out.println("Turn off the sprinkler for room " + s.getRoom().getName());s.setOn(false);}).update(sprinkler, "on")
);Rule r3 = rule("Raise the alarm when we have one or more fires").view(input(fire),exists(fire)).then(execute(() -> System.out.println("Raise the alarm")).insert(() -> new Alarm())
);Rule r4 = rule("Lower the alarm when all the fires have gone").view(input(fire),not(fire),input(alarm)).then(execute(() -> System.out.println("Lower the alarm")).delete(alarm)
);Rule r5 = rule("Status output when things are ok").view(input(alarm),not(alarm),input(sprinkler),not(sprinkler, Sprinkler::isOn)).then(execute(() -> System.out.println("Everything is ok"))
);CanonicalKieBase kieBase = new CanonicalKieBase();
kieBase.addRules(r1, r2, r3, r4, r5);KieSession ksession = kieBase.newKieSession();// phase 1
Room room1 = new Room("Room 1");
ksession.insert(room1);
FactHandle fireFact1 = ksession.insert(new Fire(room1));
ksession.fireAllRules();// phase 2
Sprinkler sprinkler1 = new Sprinkler(room1);
ksession.insert(sprinkler1);
ksession.fireAllRules();assertTrue(sprinkler1.isOn());// phase 3
ksession.delete(fireFact1);
ksession.fireAllRules();

在此示例中,可能还要注意几件事:

  • 必须执行一些重复操作才能将表达式的参数绑定到评估它的lambda表达式的形式参数。 希望可以在解决此JDK错误时使用-parameters编译参数来克服此问题。
  • any(Room.class)是bind(typeOf(Room.class))的快捷方式
  • 输入未声明数据源。 这是指出这些对象来自默认空DataSource的快捷方式(对应于Drools默认入口点)。 实际上,在此示例中,事实以编程方式插入到KieSession中。
  • 使用输入而不为其提供任何表达式的输入实际上是input(alarm),expr(alarm,a-> true)的快捷方式
  • 以同样的方式,没有条件的存在模式,例如not(fire)是not(expr(fire,f-> true))的另一个快捷方式
  • Java 8语法还允许将谓词定义为访问诸如expr(sprinkler,Sprinkler :: isOn)之类的事实的布尔属性的方法引用。
  • RHS与要执行的代码块一起,还提供了一个流畅的接口来定义在触发规则时必须执行的工作内存操作(插入/更新/删除)。 特别是,更新还获得了一个字符串变量,用于报告在更新的事实中更改过的属性的名称,例如update(sprinkler,“ on”)。 再次必须明确提供此信息,因为必须创建可执行模型而无需任何代码分析。

翻译自: https://www.javacodegeeks.com/2014/07/drools-executable-model.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/362829.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

centos7安装openjdk8

首先&#xff0c;打开openjdk安装官网 http://openjdk.java.net/install/ 输入安装命令&#xff1a; su -c "yum install java-1.8.0-openjdk" 装完之后会有提示版本跟安装的路径&#xff1b;在/usr/lib/jvm下可以查看到对应的名字&#xff0c;ls-l 配置环境变量&…

CSB文件上传漏洞 -->Day4(图片挂马)

22二号&#xff0c;冬至啦&#xff0c;深圳这边只有5&#xff08;尊嘟好冷啊&#xff09;&#xff0c;写这篇文章的时候都已经是凌晨一点了&#xff0c;相信大部分的人都在温暖的被窝里面了吧&#xff01;&#xff01;&#xff08;可怜的我&#xff0c;还得写writeup&#xff0…

微信小程序禁止刷新之后苹果端还可以下拉的问题

一、问题描述 最近在做一个小程序项目&#xff0c;需要禁止下拉刷新&#xff0c;于是在page.json里面添加了这段话 "enablePullDownRefresh":false 全局关闭下拉刷新&#xff0c;这段话确实禁止了下拉刷新&#xff0c;无论是安卓手机端还是苹果端&#xff0c;但是在…

Win32 Application和Win32 Console Application的区别

Win32 Application和Win32 Console Application都是工作在32位Windows环境的程序。其中Win32 Application就是普通的常见的窗口应用程序&#xff0c;当然有的界面做得比较个性化&#xff0c;比如圆形的、不规则形状的……它们都是所谓的GUI(Graphics User Interface图形用户接口…

调试OpenJDK

knowyourmeme.com/photos/531557 THX为mihn 有时调试Java代码还不够&#xff0c;我们需要逐步了解Java的本机部分。 我花了一些时间来实现JDK的正确状态&#xff0c;所以简短的描述可能对开始旅行的人很有用。 我将使用全新的OpenJDK 9&#xff01; 首先&#xff0c;您必须通过…

算法题解:旋转数组的最小数字

题目描述 把一个数组最开始的若干个元素搬到数组的末尾&#xff0c;我们称之为数组的旋转。输入一个非递减排序的数组的一个旋转&#xff0c;输出旋转数组的最小元素。 解题思路 将旋转数组对半分可以得到一个包含最小元素的新旋转数组&#xff0c;以及一个非递减排序的数组。新…

函数的自执行,变量提升和函数提升

其实之前虽然刚开始学习JavaScript的时候经常看到function add(){}、var addfunction(){}、function(){}之类的这种写法&#xff0c;但是具体是什么叫什么却没有去考虑过这个问题…… function add(){}这种写法叫做函数声明 var addfunction(){}这种写法叫做函数表达式 fun…

Python之机器学习-sklearn生成随机数据

sklearn-生成随机数据 import numpy as np import pandas as pd import matplotlib.pyplot as plt from matplotlib.font_manager import FontProperties from sklearn import datasets %matplotlib inline font FontProperties(fname/Library/Fonts/Heiti.ttc) 多标签分类数据…

css:学习CSS了解单位em和px的区别

在国内网站中&#xff0c;包括三大门户&#xff0c;以及“引领”中国网站设计潮流的蓝色理想&#xff0c;ChinaUI等都是使用了px作为字体单位。只有百度好歹做了个可调的表率。而在大洋彼岸&#xff0c;几乎所有的主流站点都使用em作为字体单位&#xff0c;也就是可调的。没错&…

外汇游乐场

介绍 F X Playground是基于JavaFX的原型制作工具或实时编辑器&#xff0c;它消除了编译Java代码的步骤。 这个概念并不是什么新鲜事物&#xff0c;例如在网络世界中&#xff0c;有许多HTML5 游乐场提供在线编辑器&#xff0c;使开发人员可以快速原型化或尝试各种JavaScript库。…

轻轻松松看懂Spring AOP源码

轻轻松松看懂Spring AOP源码 https://baijiahao.baidu.com/s?id1596466083334197175&wfrspider&forpc 如果对spring的核心容器和JDK动态代理、CGLIB有所了解&#xff0c;接下来再看spring AOP源码会比较容易。文中所有代码片段截图对应的spring版本是5.0。 本文内容曾…

2015年,Web 进入移动时代

最近 Morgan Stanley 发布了一份87页的报告&#xff0c;对 Internet 的未来趋势进行预测&#xff0c;报告显示&#xff0c;移动 Web 目前发展迅猛&#xff0c;包括 Kindle, iPhone, 智能手机&#xff0c;平板电脑&#xff0c;GPS 设备&#xff0c;游戏机在内的无线设备呈爆炸式…

vue2.0移除或更改的一些东西

一、vue2.0移除了$index和$key 虽然说现在很多文章说他们的代码是vue2.0版本的&#xff0c;但是有一些仔细一看&#xff0c;发现并不全是2.0版本&#xff0c;有些语法还是1.0的版本&#xff0c;比如这个$index,$key&#xff0c;这两个压根就不是2.0的写法&#xff0c;2.0早就把…

VGG16等keras预训练权重文件的下载及本地存放

VGG16等keras预训练权重文件的下载&#xff1a; https://github.com/fchollet/deep-learning-models/releases/ .h5文件本地存放目录&#xff1a; Linux下是放在“~/.keras/models/”中 Win下则放在Python的“settings/.keras/models/”中 在anaconda on win中默认是&#xff1…

Java Keystore教程

目录 1.简介 2. SSL及其工作方式 3.私钥 4.公开证书 5.根证书 6.证书颁发机构 7.证书链 8.使用Java keytool的密钥库 9.密钥库命令 10.在Apache Tomcat上使用密钥库和自签名证书配置SSL 1.简介 我们谁没有去ebay&#xff0c;亚马逊买东西或他的个人银行帐户来检查。 您是否认为…

spring AOP源码分析(一)

spring AOP源码分析&#xff08;一&#xff09; 对于springAOP的源码分析&#xff0c;我打算分三部分来讲解&#xff1a;1.配置文件的解析&#xff0c;解析为BeanDefination和其他信息然后注册到BeanFactory中&#xff1b;2.为目标对象配置增强行为以及代理对象的生成&#xff…

异或前缀和,组合数学——cf1054D

/* 每个异或前缀和sum[i]只有两个值 区间异或和不为0&#xff0c;即两个不相等的前缀和 sum[i]的两个前缀和只要标记一个就可以了&#xff0c;为了去重只用map保存最小的那个来计数 最后统计相同的前缀和时&#xff0c;为了使相同的最小&#xff0c;每个map的值要平分 */ #inc…

elementUI之switch应用的坑

前言&#xff1a; 因为项目中用到了饿了么出品的element-ui这一套ui框架&#xff0c;所以很多地方都踩在了坑里&#xff0c;前面碰到了一些&#xff0c;今天着重聊一下switch这个组件。 首先switch接受Boolean类型的数据&#xff0c;莫非是true和false。 对switch进行赋值&a…

C# 反射机制(转)

1、 什么是反射2、 命名空间与装配件的关系3、 运行期得到类型信息有什么用4、 如何使用反射获取类型5、 如何根据类型来动态创建对象6、 如何获取方法以及动态调用方法7、 动态创建委托 1、什么是反射 Reflection&#xff0c;中文翻译为反射。 这是.Net中获取运…

《软件工程导论》课后习题解答

来源&#xff1a;https://blog.csdn.net/Rong_Toa/article/details/80771976 第一章 软件工程概论 1&#xff0e;什么是软件危机&#xff1f; 软件危机是指在计算机软件的开发和维护过程中所遇到的一系列严重问题。这些问题表现在以下几个方面&#xff1a; (1)用户对开发出的软…