想象一下,你有一个工厂,通过皮带将产品带到制造过程中。在其中的某个地方,有必要根据一些商业逻辑将产品流从单个皮带输入分割到多个皮带上。也许它们需要用红色,绿色和蓝色产品的输出带分开。也许它是某种简单的负载平衡,所以产品需要根据每个输出带的百分比进行拆分。
________________
/ ___Color=Red___...
____________/ /_______________
..._Products___ ____Color=Green_...
\ \_______________
\____Color=Blue__...
或者
__________
/ ___60%___...
____________/ /_________
..._Products___ ____20%___...
\ \_________
\____20%___...
具体而言,我试图对routing functionality of ProModel进行逆向工程。路由方法应该能够在运行时进行更改,就像各个输出带的路由属性一样。 (比如改变颜色标准)。如果路由方法切换回先前定义的路由方法,则会记住所使用的设置。
为了保持我的代码概括,产品是"实体"物体,分开的带是"路线"对象,内部路由逻辑是" RoutingRule"整个输入带/内部逻辑/输出带的东西是一个" Router"。基于ProModel的使用," RoutingRule"适用于"路由器"而不是个人"路线" - 如果规则是 RouteByPercent ,则每个传出"路由"应该有一个百分比,而如果它是 RouteByAttribute ,每个"路由"将有一个属性/比较者/标准(例如"颜色"," =","蓝")设置为测试来自"实体&#34 ;
我可以看到使用策略模式可以灵活地支持和交换" RoutingRule"对象(例如ProModel链接中可能的规则列表);但是,我不太清楚如何在没有紧密耦合" RoutingRule"的情况下存储每个规则的状态信息。和#34;路线"对象。
将战略模式应用于此案例时,我应该如何存储每个路由适用的特定于路由规则的属性?我试图通过我的选项进行思考而我不会像其中任何一个一样:
m_Percent
,m_EntityAttribute
/ m_EntityComparator
/ m_EntityCriteria
...但那样会因为明显的原因而变得可怕。每当我添加一种新的RoutingRule时,我都必须将成员变量添加到Route类。Route.Attributes(strAttrName)
,它更像是RoutingRule.RouteAttributes(Route.Name).Attributes(strAttrName)
。 顺便说一下,我在VBA中执行此操作时会考虑所有限制。
答案 0 :(得分:1)
检查用某种语言编写的骨架:
class Entity { // Or call this the EntityHolder
Map attrs;
RealEntity re; // The payload
}
abstract class RouteElement {
void process(Entity entity);
Map attrs;
}
interface RouterRule {
RouteElement pickNextRouteElement(Entity e, List<RouteElement> allOutRoutes);
}
class Router extends RouteElement {
List<RouteElement> outRoutes;
RouteElement deadRoute;
RouterRule routerRule;
void process(Entity entity) {
RouteElement nextRouteElement = routerRule.pickNextRouteElement(entity, outRoutes);
if (nextRouteElement == null) {
if (deadRoute) {
deadRoute.process(entity);
}
} else {
nextRouteElement.process(entity);
}
}
void setRouterRule(RouterRule rr) {
routerRule = rr;
}
RouterRule getRouterRule() {
return routerRule;
}
void addOutRouteElement(RouteElement re) {
outRoutes.add(re);
}
void setDeadRoute(RouteElement re) {
deadRoute = re;
}
}
class ColorRouterRule implements RouterRule {
RouteElement pickNextRouteElement(Entity e, List<RouteElement> allOutRoutes) {
foreach(RouteElement re in allOutRoutes) {
if (e.getAttr("color") == re.getAttr("color") {
return re;
}
}
return null;
}
}
class RandomRouterRule implements RouterRule {
RouteElement pickNextRouteElement(Entity e, List<RouteElement> allOutRoutes) {
int rand = random(0, allOutRoutes.length());
return allOutRoutes.get(rand);
}
}
class PercentRouterRule implements RouterRule {
RouteElement pickNextRouteElement(Entity e, List<RouteElement> allOutRoutes) {
int[] weights = int[allOutRoutes.length()];
int prevWeight = 0;
for (i = 0; i < weights, i++) {
weights[i] = prevWeight + allOutRoutes.get(i).getAttr("percent");
prevWeight = weights[i];
}
int rand = random(0, prevWeight);
for (i = 0; i < weights, i++) {
if (rand <= weights[i]) {
return allOutRoutes[i];
}
}
}
}
class RouterManager {
Router routerBeingManaged;
Stack<RouterRule> oldRouterRules;
void setNewRouterRule(RouterRule rr) {
oldRouterRules.push(routerBeingManaged.getRouterRule());
routerBeingManaged.setRouterRule(rr);
}
void revertToOldRouterRule() {
routerBeingManaged.setRouterRule(ooldRouterRules.pop());
}
..
}
class Route extends RouteElement {
List<RouteElement> route;
void addRouteElement(..) {
..
}
void process(Entity entity) {
foreach(RouteElement as re in route) {
re.process(entity);
}
}
}
class MyApp {
void main() {
Route r = new Route();
// Build the route
r.addRouteElement(...);
r.addRouteElement(...);
Router router1 = new Router();
router1.addOutRouteElement(..);
router1.addOutRouteElement(..);
router1.addOutRouteElement(..);
RouterManager router1Mgr = new RouterManager(router1);
router1Mgr.setRouterRule(new RandomRouterRule());
r.addRouteElement(router1);
r.addRouteElement(...);
r.addRouteElement(...);
// Get entities from somewhere
r.process(entity);
// Change the router rule
router1Mgr.setRouterRule(new PercentRouterRule());
// Get entities from somewhere
r.process(entity);
// Revert the router rule
router1Mgr.revertToOldRouterRule();
// Get entities from somewhere
r.process(entity);
}
}