我想写一个总是执行预定义例程的模板类。一种方法是抽象的,因此实现类可以定义对象的自定义处理操作。
班级必须严格无国籍。没有参数可以保存。
@Service
abstract class BaseService {
void invoke(DataVO data) {
prepare(data);
Response rsp = process(data);
validate(rsp);
}
void prepare(DataVO data) {
//general data preparation
}
void validate(Response rsp) {
//general validation
}
//each implementation can provide custom processor
abstract Response process(DataVO);
}
我想这样用:
//从套接字获取数据的服务
@Service
class MySocket {
@Autowired
private List<BaseService> services;
public income(InputStream stream) {
//convert stream to data objects, eg DataVO, CustomerVO based on the input
//then find d
action = getActionType(stream);
for (BaseService service : services) {
if (service.canHandle(action)) {
service.invoke(dataVO);
//sometime, based on the action, provide additional params like CustomerVO etc
}
}
}
}
问题:有时我想要实现,在process()
方法中使用2-3个参数,例如process(DataVO, CustomerVO, int)
。使用上面的代码当然不可能。但是我怎么能重写这个以便执行模板方法,并且只执行带有变量参数的进程方法?
答案 0 :(得分:1)
这是一个非常简单和抽象的解决方案。首先,我们定义一个ServiceContext
类作为基类,用于保存稍后在服务实现中使用的所有引用(它基本上是一个DTO)。
class ServiceContext {
// ...
}
服务可以根据需要扩展此基类,以便他们可以定义自己的上下文子类:
class SpecificServiceContext extends ServiceContext {
// This service only needs a DataVO object
private DataVO data;
}
当客户端代码在注册服务中迭代时选择服务时,它可以创建一个上下文对象,其中包含所需内容的引用。请注意,这里的service.getContext()
只是一个例子来说明它是如何工作的。
@Service
class MySocket {
// ...
public income(InputStream stream) {
// ...
for (BaseService service : services) {
if (service.canHandle(action)) {
// Here, getContext() returns a subclass of ServiceContext
// that holds the service specific objects
// (in this example dataVO)
ServiceContext context = service.getContext();
service.invoke(context);
}
}
}
}
BaseService在不了解实际服务或类型的情况下完成了旧工作。
@Service
abstract class BaseService {
void invoke(ServiceContext context) {
// ...
Response rsp = process(context);
// ...
}
abstract Response process(ServiceContext context);
}
最后,BaseService
子类可以使用我们之前封装的上下文来定义任意行为。
@Service
class SpecificService extends BaseService {
Response process(ServiceContext context) {
SpecificServiceContext specificContext = (SpecificServiceContext) context;
// Here, we can do whatever we want. Wow. Much happy.
}
}
答案 1 :(得分:0)
只需创建方法调用的新定义
void invoke(DataVO data, CustomerVO customer, int i) {
prepare(data);
Response rsp = process(data, customer, i);
validate(rsp);
}
和方法流程一起出现:
//each implementation can provide custom processor
abstract Response process(DataVO data, CustomerVO customer, int i);
答案 2 :(得分:0)
您可以制作包含流程可能需要的所有数据的Data Transfer Object。
class ServiceDTO{
public DataV0 getDataV0(){
...
}
public CustomerV0 getCustomerV0(){
...
}
...etc
}
现在,您的流程方法采用ServiceDTO
abstract Response process(ServiceDTO);
public income(InputStream stream) {
//convert stream to DTO based on the input
ServiceDTO dto = ...
//then find d
action = getActionType(stream);
for (BaseService service : services) {
if (service.canHandle(action)) {
service.invoke(dto);
}
}
}
关于这一点的好处是过程方法永远不会改变。如果您需要添加更多要处理的内容,可以向新的DTO类添加方法。旧代码不会破坏,因为它不会调用新方法,方法签名保持不变。