java commons-chain_Apache commons chain 初探
Apache commons chain 是什么
Apache common chain 是對責任鏈設計模式的改造封裝,讓使用者更加方便的使用。
簡單回顧一下責任鏈設計模式
在閻宏博士的《JAVA與模式》一書中開頭是這樣描述責任鏈(Chain of Responsibility)模式的:
責任鏈模式是一種對象的行為模式。在責任鏈模式里,很多對象由每一個對象對其下家的引用而連接起來形成一條鏈。請求在這個鏈上傳遞,直到鏈上的某一個對象決定處理此請求。發出這個請求的客戶端并不知道鏈上的哪一個對象最終處理這個請求,這使得系統可以在不影響客戶端的情況下動態地重新組織和分配責任
關鍵點:
鏈是一系列節點的集合
鏈的各個節點可隨意拆分和組裝
使多個對象都有機會處理請求,從而避免請求的發送者和接受者之間的耦合關系, 將這個對象連成一條鏈,并沿著這條鏈傳遞該請求,直到有一個對象處理他為止。
責任鏈適用的場景
有多個的對象可以處理一個請求,哪個對象處理該請求運行時刻自動確定。
你想在不明確指定接受者的情況下,想過個對象中的一個提交一個請求。
可處理一個請求的對象集合應該被動態指定。
簡單例子
abstract class Handler {
private Handler nextHandler;
public Handler getNextHandler() {
return nextHandler;
}
public void setNextHandler(Handler nextHandler) {
this.nextHandler = nextHandler;
}
public abstract void doHandler();
}
class ConcreteHandler extends Handler {
@Override
public void doHandler() {
if (getNextHandler() != null) {
System.out.println("還有責任鏈");
getNextHandler().doHandler();
} else {
System.out.println("我自己處理" + toString());
}
}
}
設計模式主體架構:
角色:
抽象處理者角色(Handler):定義出一個處理請求的接口。如果需要,接口可以定義 出一個方法以設定和返回對下家的引用。這個角色通常由一個Java抽象類或者Java接口實現。 具體處理者角色(ConcreteHandler):具體處理者接到請求后,可以選擇將請求處理掉,或者將請求傳給下家。由于具體處理者持有對下家的引用,因此,如果需要,具體處理者可以訪問下家。 抽象處理者角色
public abstract class Handler {
/**
* 持有后繼的責任對象
*/
protected Handler successor;
/**
* 示意處理請求的方法,雖然這個示意方法是沒有傳入參數的
* 但實際是可以傳入參數的,根據具體需要來選擇是否傳遞參數
*/
public abstract void handleRequest();
/**
* 取值方法
*/
public Handler getSuccessor() {
return successor;
}
/**
* 賦值方法,設置后繼的責任對象
*/
public void setSuccessor(Handler successor) {
this.successor = successor;
}
}
具體處理者角色
public class ConcreteHandler extends Handler {
/**
* 處理方法,調用此方法處理請求
*/
@Override
public void handleRequest() {
/**
* 判斷是否有后繼的責任對象
* 如果有,就轉發請求給后繼的責任對象
* 如果沒有,則處理請求
*/
if(getSuccessor() != null)
{
System.out.println("放過請求");
getSuccessor().handleRequest();
}else
{
System.out.println("處理請求");
}
}
}
客戶端類:
public class Client {
public static void main(String[] args) {
//組裝責任鏈
Handler handler1 = new ConcreteHandler();
Handler handler2 = new ConcreteHandler();
handler1.setSuccessor(handler2);
//提交請求
handler1.handleRequest();
}
}
Apache CommonsChain
CommonsChain實現了Chain of Responsebility和Command模式,其中的Catalog + 配置文件的方式使得調用方和Command的實現方的耦合度大大的降低,提高了靈活性。
如何使用
簡單寫了一個實現:
/**
*
Test implementation of Chain that exposes the
* getCommands() method publicy.
*/
public class TestChain extends ChainBase {
/**
* 獲取責任鏈中所有加入的命令
* @return 責任鏈中的命令
*/
public Command[] getCommands() {
return (commands);
}
public static void main(String[] args) throws Exception {
TestChain testChain=new TestChain();
Context context=new ContextBase();
/**
* 加入執行命令1
*/
testChain.addCommand(new Command() {
public boolean execute(Context context) throws Exception {
System.out.println("執行命令1");
return false;
}
});
/**
* 加入執行命令2
* 注意:返回值為true 表示執行到此為止
*/
testChain.addCommand(new Command() {
public boolean execute(Context context) throws Exception {
System.out.println("執行命令2");
return true;
}
});
/**
* 加入執行命令3
*/
testChain.addCommand(new Command() {
public boolean execute(Context context) throws Exception {
System.out.println("執行命令3");
return false;
}
});
//執行鏈中的命令
testChain.execute(context);
//打印鏈中的所有命令
Command[] commands=testChain.getCommands();
for(Command command:commands){
System.out.println(command.getClass());
}
}
}
** 執行結果 **
- 執行命令1
- 執行命令2
- class org.apache.commons.chain.config.TestChain$1
- class org.apache.commons.chain.config.TestChain$2
- class org.apache.commons.chain.config.TestChain$3
基本對象
1. Command接口。它是Commons Chain中最重要的接口,表示在Chain中的具體某一步要執行的命令。它只有一個方法:boolean execute(Context context)。如果返回true,那么表示Chain的處理結束,Chain中的其他命令不會被調用;返回false,則Chain會繼續調用下一個Command,直到:
[x] > Command返回true;
[x] > Command拋出異常;
[x] > Chain的末尾;
2. Context接口。它表示命令執行的上下文,在命令間實現共享信息的傳遞。Context接口的父接口是Map,ContextBase實現了Context。對于web環境,可以使用WebContext類及其子類(FacesWebContext、PortletWebContext和ServletWebContext)。
3. Chain接口。它表示“命令鏈”,要在其中執行的命令,需要先添加到Chain中。Chain的父接口是Command,ChainBase實現了它。
使用配置文件
test-config.xml
className="org.apache.commons.chain.impl.DelegatingCommand"/>
className="org.apache.commons.chain.impl.DelegatingCommand"/>
className="org.apache.commons.chain.impl.ExceptionCommand"/>
裝入配置文件
public class ConfigParserTestCase extends TestCase {
private static final String DEFAULT_XML =
"/org/apache/commons/chain/config/test-config.xml";
// ------------------------------------------------------------ Constructors
/**
* Construct a new instance of this test case.
*
* @param name Name of the test case
*/
public ConfigParserTestCase(String name) {
super(name);
}
// ------------------------------------------------------ Instance Variables
/**
*
The Catalog to contain our configured commands.
*/
protected Catalog catalog = null;
/**
*
The Context to use for execution tests.
*/
protected Context context = null;
/**
*
The ConfigParser instance under test.
*/
protected ConfigParser parser = null;
// ---------------------------------------------------- Overall Test Methods
/**
* Set up instance variables required by this test case.
*/
public void setUp() {
catalog = new CatalogBase();
context = new ContextBase();
parser = new ConfigParser();
}
/**
* Return the tests included in this test suite.
*/
public static Test suite() {
return (new TestSuite(ConfigParserTestCase.class));
}
/**
* Tear down instance variables required by this test case.
*/
public void tearDown() {
parser = null;
context = null;
catalog = null;
}
/**
執行測試方法
**/
public void testExecute2c() throws Exception {
load(DEFAULT_XML);
try {
catalog.getCommand("Execute").execute(context);
} catch (ArithmeticException e) {
assertEquals("Correct exception id",
"3", e.getMessage());
}
checkExecuteLog("1/2/3");
}
/**
從配置文件中加載配置信息
**/
protected void load(String path) throws Exception {
parser.parse(this.getClass().getResource(path));
catalog = CatalogFactoryBase.getInstance().getCatalog();
}
}
注意:使用配置文件的話,需要使用Commons Digester。而Digester則依賴:Commons Collections、Commons Logging和Commons BeanUtils。
4. Filter接口。它的父接口是Command,它是一種特殊的Command。除了Command的execute,它還包括一個方法:boolean postprocess(Context context, Exception exception)。Commons Chain會在執行了Filter的execute方法之后,執行postprocess(不論Chain以何種方式結束)。Filter的執行execute的順序與Filter出現在Chain中出現的位置一致,但是執行postprocess順序與之相反。如:如果連續定義了filter1和filter2,那么execute的執行順序是:filter1 -> filter2;而postprocess的執行順序是:filter2 -> filter1。
5. Catalog接口。它是邏輯命名的Chain和Command集合。通過使用它,Command的調用者不需要了解具體實現Command的類名,只需要通過名字就可以獲取所需要的Command實例。
6.
的使用。配置文件的引入,使得Commons Chain的靈活性大大的提高。在實際的使用過程中,存在著同一個Command被多個Chain使用的情形。如果每次都書寫Command的類名,尤其是前面的包名特別長的情況下,是非常枯燥的。而
的作用就是為了解決這樣的麻煩。通過定義Command和Chain的別名,來簡化書寫。配置文件,可以書寫成:
className="org.apache.commons.chain.generic.LookupCommand"/>
參考:
總結
以上是生活随笔為你收集整理的java commons-chain_Apache commons chain 初探的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java switch char_Jav
- 下一篇: mysql构建器 批量插入_mysqlb