java - Chain of responsibility pattern - tight coupling with descendants -
i came problem how put actions chain possibility pass additional parameters during processing of action.
let's consider simple chain of processes. input object representing image. first image resized, deployed ftp , saved db. using chain of responsibility pattern, calling this:
imageprocessor p = new imageresizer(desiredsize); p.setnext(new (new imagedeployer(ftpserver, path))); p.setnext(new (new imagedbsaver(dbconnection, table))); p.process(image); p.close();
this working 1 image. process images in loop , set desiredsize , path there. cannot create , close connections every time, code has spread:
imageprocessor p = new imageresizer(); p.setnext(new (new imagedeployer(ftpserver))); p.setnext(new (new imagedbsaver(dbconnection, table))); for(image image : images) { p.process(image, size, path); } p.close();
a problem of solution imageprocessor shouldn't know size , path. in case when used imagedbsaver parameters size , path doesn't make sense.
better way how it?
i guess robust solution in case add kind of processing context.
in simplest case, can (1) use, example map<string, object>
this, (2) pack arguments specific various processors, (3) pass p.process(...)
, (4) extract, example size
in processor resizes image.
this way you'll flexibility add new arguments without need change signature of imageprocessor
, keeping implementers decoupled form 1 another.
the real world example of similar request\session\servlet contexts in java ee. can put stuff them on various lifecycle stages (for example security configuration options urls should require auth) , fetch stuff needed (for example in filter block\allow access resource based on auth requirements).
update
updating answer code example demonstrate idea.
so, somewhere in code have place build processor chain:
imageprocessor p = new imageresizer(desiredsize); p.setnext(new (new imagedeployer(ftpserver, path))); p.setnext(new (new imagedbsaver(dbconnection, table)));
in (possibly) other place create , configure processing context (it not required configure processors in 1 place):
map<string, object> context = new hashmap<string, object>(); context.put("image_width", new integer(640));
in place in code processing, passing context (i reuse context processings might use different contexts every image):
for(image image : images) { p.process(image, context); } p.close();
now, somewhere in imageresizer
:
@override void process(image image, map<string, object> context) { // ... integer imagewidth = (integer) context.get("image_width"); // ... }
so, context common place helps deliver data specific processors, abstracting details data , decoupling specific processors 1 another.
Comments
Post a Comment