关于Policy的实用设计模式,有哪些具体应用场景?

2026-05-25 08:104阅读0评论SEO问题
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1257个文字,预计阅读时间需要6分钟。

关于Policy的实用设计模式,有哪些具体应用场景?

以下是对原文的简化

原文:以下文章基于Policy-based design的构思,而非传统的Strategy模式。Strategy模式是应用较为广泛的模式之一,在我没有系统学习设计模式之前,我就直接使用该模式的思考进行设计。我想从一个‘策略’的角度出发。

简化版:本文以Policy-based design为设计理念,区别于常规的Strategy模式。在我未系统学习设计模式前,我直接用Strategy模式的思路进行设计。我希望从策略角度出发。

以下文章为Policy-based design的想法,不是经典的Strategy模式。

Strategy模式是应用比较广泛的模式之一,在我没有系统学习设计模式之前,我就一直使用该模式的思想进行设计。我想从一个例子来讲述该模式,假设有一个PDA的订餐系统,前端是Windows Mobile,后端为Web服务。服务员的PDA可以做以下三种操作,1.使用用户名密码登录到系统中。2.帮客户点菜下订单。3.对用餐结帐。前端不包含business logic,只是把请求通过WebService发送到后台。后台负责接收,处理请求,并回应处理结果。前后台通信可以通过webservice,remoting,WCF甚至socket进行通信,但这不是这篇文章讨论的内容,文章主要关注后台的设计。最直观简单的设计就是一个函数处理一种请求,实现如下:

publicenumRequestType
{
Login,
Order,
Payment
}

publicboolProcessRequest(RequestTypetype,DataSetds)
{
switch(type)
{
caseRequestType.Login:
returnProcessLogin(ds);
break;
caseRequestType.Order:
returnProcessOrder(ds);
break;
caseRequestType.Payment:
returnProcessPayment(ds);
break;
}
}

但是,我们来闻闻这段代码的臭味道,大量使用switch,如果要增加请求处理,就需要增加case语句。所以我们使用strategy模式进行重构。在具体应用之前先简单介绍一下strategy模式的一般实现。

关于Policy的实用设计模式,有哪些具体应用场景?

Strategy定义父类的算法接口,所有子类都必须实现该接口,Context负责管理管理各个Strategy。Client不需要关心Strategy以及其子类的具体算法实现,只是把请求交给Context进行处理。

在我们的情景下,Stragtegy模式的现实如下:


publicenumRequestType
{
Login,
Order,
Payment
}

publicinterfaceRequestHandler
{
boolProcessRequest(DataSetds);
}

publicclassLoginHandler:RequestHandler
{
publicboolProcessRequest(DataSetds)
{
//longintothesystem
returntrue;
}

}

publicclassOrderHandler:RequestHandler
{
publicboolProcessRequest(DataSetds)
{
//makeanorder
returntrue;
}

}

publicclassPaymentHandler:RequestHandler
{
publicboolProcessRequest(DataSetds)
{
//makeapayment
returntrue;
}

}

publicsealedclassRequestManager
{
privateDictionary<RequestType,RequestHandler>handlers;

publicRequestManager()
{
handlers=newDictionary<RequestType,RequestHandler>();

//itcanusefactorypatternhere.
handlers[RequestType.Login]=newLoginHandler();
handlers[RequestType.Order]=newOrderHandler();
handlers[RequestType.Payment]=newPaymentHandler();
}

publicboolProcess(RequestTypetype,DataSetds)
{
if(handlers.ContainsKey(type))
{
returnhandlers[type].ProcessRequest(ds);
}
returnfalse;
}
}

在Strategy模式的定义里面,Strategy抽象类定义要实现的算法接口,我认为应用范围不仅仅在算法,只要有共同点操作就可以定义这样的接口,定义这个接口的目的是制定一个契约,子类必须实现这个接口,也就是必须厉行这个契约。在我们的案例里面RequestHandler就是Strategy父类,这里可以定义为interface或者abstract class,这视乎于RequestHandler是否有子类共同的逻辑,如果有共同逻辑就定义为abstract class,把共同逻辑封装到protected的成员里面,没有就定义成interface。LoginHandler,OrderHandler和PaymentHandler等为RequestHandler的子类,他们必须实现ProcessRequest方法。RequestManager为Handlers的管理类,他管理着请求类型和处理类的映射关系,client只要调用RequestManager的Process进行处理,不用关心具体的处理类。Strategy很适合于编写framework,framework把总统的处理流程规定好,具体的交易流程根据interface来实现具体的处理类。例如我们这个系统扩展一下,规定每笔交易都需要操作数据库,写文件日志,进行侦听三步操作,那么可以定义三个处理的接口,每个处理类都需要实现相应的接口来满足总体流程。

当新增加交易请求处理类的时候,也必须实现OperateDB,Log和Audit接口。这样framework和具体业务流程就分开了。

Strategy模式应用广泛,不仅仅用于请求的处理,可以用于有共同的Input,共同的Output,使用不同的处理算法来处理的情景,这里共同的Input和共同的Output可以指使用共同的父类作为Input或者output,例如下面是一个网络监控系统中的告警处理引擎(Alarm analysis engine),Input是采集于网络的源数据(Raw Data),Output是相应的告警对象。

publicenumNetworkEquimentType
{
Router,
Switch
}

//Input
publicabstractclassRawData
{
publicNetworkEquimentTypeType{get;set;}
publicstringData{get;set;}
}

publicclassRouterData:RawData
{
//specificproperties
publicstringRouterName{get;set;}
}

publicclassSwitchData:RawData
{
//specificproperties
publicstringSwitchName{get;set;}
}

//Output
publicclassAlarm
{
publicintLevel{get;set;}
publicintType{get;set;}
}

publicclassRouterAlarm:Alarm
{
//specificproperties
publicstringRouterName{get;set;}
}

publicclassSwitchAlarm:Alarm
{
//specificproperties
publicstringSwitchName{get;set;}
}

//Strategy
publicinterfaceAlarmHandler
{
AlarmAnalyseRowData(RawDatard);
}

publicclassRouterAlarmHandler:AlarmHandler
{
publicAlarmAnalyseRowData(RawDatard)
{
RouterDatarouterData=rdasRouterData;
RouterAlarmra=newRouterAlarm();
returnra;
}

}

publicclassSwitchAlarmHandler:AlarmHandler
{
publicAlarmAnalyseRowData(RawDatard)
{
SwitchDataswitchData=rdasSwitchData;
SwitchAlarmsa=newSwitchAlarm();
returnsa;
}
}

Strategy这种设计思想应用十分广泛,在纯C的世界,可以使用表驱动来实现Strategy,在C++的世界可以使用纯OO实现,也可以使用模板实现所谓的Policy-based design,这是Loki库的基础。

Jake's Blog in 自由互联 -- 精简开发 无线生活

本文共计1257个文字,预计阅读时间需要6分钟。

关于Policy的实用设计模式,有哪些具体应用场景?

以下是对原文的简化

原文:以下文章基于Policy-based design的构思,而非传统的Strategy模式。Strategy模式是应用较为广泛的模式之一,在我没有系统学习设计模式之前,我就直接使用该模式的思考进行设计。我想从一个‘策略’的角度出发。

简化版:本文以Policy-based design为设计理念,区别于常规的Strategy模式。在我未系统学习设计模式前,我直接用Strategy模式的思路进行设计。我希望从策略角度出发。

以下文章为Policy-based design的想法,不是经典的Strategy模式。

Strategy模式是应用比较广泛的模式之一,在我没有系统学习设计模式之前,我就一直使用该模式的思想进行设计。我想从一个例子来讲述该模式,假设有一个PDA的订餐系统,前端是Windows Mobile,后端为Web服务。服务员的PDA可以做以下三种操作,1.使用用户名密码登录到系统中。2.帮客户点菜下订单。3.对用餐结帐。前端不包含business logic,只是把请求通过WebService发送到后台。后台负责接收,处理请求,并回应处理结果。前后台通信可以通过webservice,remoting,WCF甚至socket进行通信,但这不是这篇文章讨论的内容,文章主要关注后台的设计。最直观简单的设计就是一个函数处理一种请求,实现如下:

publicenumRequestType
{
Login,
Order,
Payment
}

publicboolProcessRequest(RequestTypetype,DataSetds)
{
switch(type)
{
caseRequestType.Login:
returnProcessLogin(ds);
break;
caseRequestType.Order:
returnProcessOrder(ds);
break;
caseRequestType.Payment:
returnProcessPayment(ds);
break;
}
}

但是,我们来闻闻这段代码的臭味道,大量使用switch,如果要增加请求处理,就需要增加case语句。所以我们使用strategy模式进行重构。在具体应用之前先简单介绍一下strategy模式的一般实现。

关于Policy的实用设计模式,有哪些具体应用场景?

Strategy定义父类的算法接口,所有子类都必须实现该接口,Context负责管理管理各个Strategy。Client不需要关心Strategy以及其子类的具体算法实现,只是把请求交给Context进行处理。

在我们的情景下,Stragtegy模式的现实如下:


publicenumRequestType
{
Login,
Order,
Payment
}

publicinterfaceRequestHandler
{
boolProcessRequest(DataSetds);
}

publicclassLoginHandler:RequestHandler
{
publicboolProcessRequest(DataSetds)
{
//longintothesystem
returntrue;
}

}

publicclassOrderHandler:RequestHandler
{
publicboolProcessRequest(DataSetds)
{
//makeanorder
returntrue;
}

}

publicclassPaymentHandler:RequestHandler
{
publicboolProcessRequest(DataSetds)
{
//makeapayment
returntrue;
}

}

publicsealedclassRequestManager
{
privateDictionary<RequestType,RequestHandler>handlers;

publicRequestManager()
{
handlers=newDictionary<RequestType,RequestHandler>();

//itcanusefactorypatternhere.
handlers[RequestType.Login]=newLoginHandler();
handlers[RequestType.Order]=newOrderHandler();
handlers[RequestType.Payment]=newPaymentHandler();
}

publicboolProcess(RequestTypetype,DataSetds)
{
if(handlers.ContainsKey(type))
{
returnhandlers[type].ProcessRequest(ds);
}
returnfalse;
}
}

在Strategy模式的定义里面,Strategy抽象类定义要实现的算法接口,我认为应用范围不仅仅在算法,只要有共同点操作就可以定义这样的接口,定义这个接口的目的是制定一个契约,子类必须实现这个接口,也就是必须厉行这个契约。在我们的案例里面RequestHandler就是Strategy父类,这里可以定义为interface或者abstract class,这视乎于RequestHandler是否有子类共同的逻辑,如果有共同逻辑就定义为abstract class,把共同逻辑封装到protected的成员里面,没有就定义成interface。LoginHandler,OrderHandler和PaymentHandler等为RequestHandler的子类,他们必须实现ProcessRequest方法。RequestManager为Handlers的管理类,他管理着请求类型和处理类的映射关系,client只要调用RequestManager的Process进行处理,不用关心具体的处理类。Strategy很适合于编写framework,framework把总统的处理流程规定好,具体的交易流程根据interface来实现具体的处理类。例如我们这个系统扩展一下,规定每笔交易都需要操作数据库,写文件日志,进行侦听三步操作,那么可以定义三个处理的接口,每个处理类都需要实现相应的接口来满足总体流程。

当新增加交易请求处理类的时候,也必须实现OperateDB,Log和Audit接口。这样framework和具体业务流程就分开了。

Strategy模式应用广泛,不仅仅用于请求的处理,可以用于有共同的Input,共同的Output,使用不同的处理算法来处理的情景,这里共同的Input和共同的Output可以指使用共同的父类作为Input或者output,例如下面是一个网络监控系统中的告警处理引擎(Alarm analysis engine),Input是采集于网络的源数据(Raw Data),Output是相应的告警对象。

publicenumNetworkEquimentType
{
Router,
Switch
}

//Input
publicabstractclassRawData
{
publicNetworkEquimentTypeType{get;set;}
publicstringData{get;set;}
}

publicclassRouterData:RawData
{
//specificproperties
publicstringRouterName{get;set;}
}

publicclassSwitchData:RawData
{
//specificproperties
publicstringSwitchName{get;set;}
}

//Output
publicclassAlarm
{
publicintLevel{get;set;}
publicintType{get;set;}
}

publicclassRouterAlarm:Alarm
{
//specificproperties
publicstringRouterName{get;set;}
}

publicclassSwitchAlarm:Alarm
{
//specificproperties
publicstringSwitchName{get;set;}
}

//Strategy
publicinterfaceAlarmHandler
{
AlarmAnalyseRowData(RawDatard);
}

publicclassRouterAlarmHandler:AlarmHandler
{
publicAlarmAnalyseRowData(RawDatard)
{
RouterDatarouterData=rdasRouterData;
RouterAlarmra=newRouterAlarm();
returnra;
}

}

publicclassSwitchAlarmHandler:AlarmHandler
{
publicAlarmAnalyseRowData(RawDatard)
{
SwitchDataswitchData=rdasSwitchData;
SwitchAlarmsa=newSwitchAlarm();
returnsa;
}
}

Strategy这种设计思想应用十分广泛,在纯C的世界,可以使用表驱动来实现Strategy,在C++的世界可以使用纯OO实现,也可以使用模板实现所谓的Policy-based design,这是Loki库的基础。

Jake's Blog in 自由互联 -- 精简开发 无线生活