2009年8月24日 星期一

Jakarta 介紹


Apache Ant Project

Apache Avalon Project
是一套面向?件的?程工程
Apache Cocoon Project
是一套XML框架


Apache DB Project
Torque
   ?
OJB
   O/R mapping
  
Apache Excalibur Project
Excalibur
  輕量的可嵌入式反向控制容器?
  
Apache Geronimo Project
Geronimo
   j2ee container ?
  
Apache Gump Project
Gump
   ?
  
Apache HTTP WebServer Project
HTTP WebServer
  
  
Apache James Project
James
  
  
Apache Logging Services Project
Log4J
  
  
Apache Maven Project
Maven
   POM(工程對象模型?)
  
Apache Portals Project
Jetspeed-1
  
Jetspeed-2
  
  
Apache Struts Project
Struts


APIs , tools, 等

BCEL
  The Byte Code Engineering Library (formerly known as JavaClass) 分析java class?
BSF
  Bean Scripting Framework (BSF),bean script框架? 讓script可以取得java object?
Commons
  Attributes
Runtime API to metadata attributes such as doclet tags.
BeanUtils
Easy-to-use wrappers around the Java reflection and introspection APIs.
Betwixt
Services for mapping JavaBeans to XML documents, and vice versa.
Chain
"Chain of Responsibility" pattern implemention.
定義執行順序
it should be feasible to utilize the Chain of Responsibility APIs in the "front controller" of a web application framework (such as Struts),
CLI
Command Line arguments parser.

參考:
http://tech.ddvip.com/2008-10/122343744475087.html
Codec
General encoding/decoding algorithms (for example phonetic, base64, URL).
Collections
Extends or augments the Java Collections Framework.
Compress
Defines an API for working with tar, zip and bzip2 files.
Configuration
Reading of configuration/preferences files in various formats.
Daemon
Alternative invocation mechanism for unix-daemon-like java code.
DBCP
Database connection pooling services.
DbUtils
JDBC helper library.
Digester
XML-to-Java-object mapping utility.
Discovery
Tools for locating resources by mapping service/reference names to resource names.
EL
Interpreter for the Expression Language defined by the JSP 2.0 specification.
Email
Library for sending e-mail from Java.
Exec
API for dealing with external process execution and environment management in Java.
FileUpload
File upload capability for your servlets and web applications.
IO
Collection of I/O utilities.
JCI
Java Compiler Interface
Jelly
XML based scripting and processing engine.
Jexl
Expression language which extends the Expression Language of the JSTL.
JXPath
Utilities for manipulating Java Beans using the XPath syntax.
Lang
Provides extra functionality for classes in java.lang.
Launcher
Cross platform Java application launcher.
Logging
Wrapper around a variety of logging API implementations.
Math
Lightweight, self-contained mathematics and statistics components.
Modeler
Mechanisms to create Model MBeans compatible with JMX specification.
Net
Collection of network utilities and protocol implementations.
Pool
Generic object pooling component.
Primitives
Smaller, faster and easier to work with types supporting Java primitive types.
Proxy
Library for creating dynamic proxies.
Sanselan
A pure-Java image library.
SCXML
An implementation of the State Chart XML specification aimed at creating and maintaining a Java SCXML engine. It is capable of executing a state machine defined using a SCXML document, and abstracts out the environment interfaces.
Transaction
Implementations for multi level locks, transactional collections and transactional file access.
Validator
Framework to define validators and validation rules in an xml file.
VFS
Virtual File System component for treating files, FTP, SMB, ZIP and such like as a single logical file system.
ECS
  The Element Construction Set ?
JMeter
  
ORO
  文本處理工具, 提供perl5.0兼容的regex, AWK-like regex, glob 表示式, 提供替換,分割,文件名稱等功能
POI
excel ?
Regexp
  
Taglibs
  jsp用
Watchdog
  檢查servlet或jsp容器執行情況
  
frameworker
Cactus
  Cactus 測試框架 ? 針對server端的java code (如servlets, EJBs, tag libraries, filters, ...)
HiveMind
  服務與配置的核心 ?
Lucene

Tapestry

Turbine

Velocity

2009年8月20日 星期四

Design Pattern - Iterator Pattern

Iterator Pattern

假設, 各種飲料店實作, 儲存資料的方式都不同時...

public class TeaBeverage{

ArrayList allTea;

public TeaBeverage{

allTea = new ArrayList();
Item item = new Item();
item.setName("紅茶");
allTea.add(item);

item = new Item();
item.setName("奶茶");
allTea.add(item);
}

public ArrayList getAllItem(){
return allTea;
}
}

public class CafeBeverage{

ArrAllCafe[] arrAllCafe;

public CafeBeverage{

arrAllCafe = new ArrAllCafe[2];

Item item = new Item();
item.setName("紅茶");
arrAllCafe[0] = item;

item = new Item();
item.setName("奶茶");
arrAllCafe[1] = item;
}

public ArrayList getAllItem(){
return arrAllCafe;
}
}


這時, 我們若要取出tea, cafe的所有資料, 它們return的類型是不同的

所以若這二個class能針對interface實現, 我們在使用時, 也針對這interface

好處:
1.把實作的儲存方式封裝起來
2.解藕


public interface IIterator{

boolean hasNext();
Object next();
}

public class CafeBeverageIterator implements IIterator{

ArrAllCafe[] arrAllCafe;
int position = 0;

public CafeBeverageIterator(ArrAllCafe[] arrAllCafe){
this.arrAllCafe = arrAllCafe;
}

public Object next(){
Item item = arrAllCafe[position];
position = position + 1;
return item;
}

public boolean hasNext(){
if(position >= arrAllCafe.length || arrAllCafe[position] == null){
return false;
}else{
return true;
}
}
}


修改原本的CafeBeverage, 改成回傳Iterator interface

public class CafeBeverage{

//同上

//public ArrayList getAllItem(){
//return arrAllCafe;
//}

public IIterator createIterator(){
return CafeBeverageIterator(arrAllCafe);
}
}


未完

2009年8月18日 星期二

Lang-其它好用的 Utils

lang.time 底下好用的 Utils (org.apache.commons.lang.time)

// 將日期轉為字串
Date date1 = new Date();
String formatDate = DateFormatUtils.format(date1, "yyyy-MM-dd");
System.out.println(formatDate);

// 將字串轉為日期
Date date2 = DateUtils.parseDate(formatDate, new String[] {"yyyyMMdd", "yyyy-MM-dd" });
System.out.println(date2);

// 只有比較日期, 沒有比較時間, 所以會回傳 true
boolean isSameDay = DateUtils.isSameDay(date1, date2);
System.out.println(isSameDay);


lang.builder 底下好用的 Utils (org.apache.commons.lang.builder)
#) EqualsBuilder 要 override equals 時,

public boolean equals(Object obj) {
if (obj == null) { return false; }
if (obj == this) { return true; }
if (obj.getClass() != getClass()) {
return false;
}
MyClass rhs = (MyClass) obj;
return new EqualsBuilder()
.appendSuper(super.equals(obj))
.append(field1, rhs.field1)
.append(field2, rhs.field2)
.append(field3, rhs.field3)
.isEquals();
}
// or
public boolean equals(Object obj) {
return EqualsBuilder.reflectionEquals(this, obj);
}



#) HashCodeBuilder 要 override hashCode 時,

public class Person {
String name;
int age;
boolean smoker;
...

public int hashCode() {
// you pick a hard-coded, randomly chosen, non-zero, odd number
// ideally different for each class
return new HashCodeBuilder(17, 37).
append(name).
append(age).
append(smoker).
toHashCode();
}
}
// or
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}


#) ToStringBuilder 要看物件裡有什麼內容時,
1. override toString()

public class Person {
String name;
int age;
boolean smoker;

...

public String toString() {
return new ToStringBuilder(this).
append("name", name).
append("age", age).
append("smoker", smoker).
toString();
}
}

2. 直接將 Object 印出來

Person P = new Person();
p.setName("hank");
...
ToStringBuilder.reflectionToString(p);
// or
ToStringBuilder.reflectionToString(ToStringStyle.MULTI_LINE_STYLE, p);

Lang-StringUtils

Jakarta 中 的 common-lang, 提供許多 java.lang.* 額外的 methods, 這次先說明 StringUtils 的一些常用的範例.


import org.apache.commons.lang.StringUtils;


public class StringUtilsDemo {

/**
* 1. Checks if a String is whitespace, empty ("") or null. (判斷 string 是否是空白, "" 或 null)
*/
public static void demoBlank() {
String str = " ";
System.out.println(StringUtils.isBlank(str)); // true

str = " abc ";
System.out.println(StringUtils.isBlank(str)); // false

str = " "; // 全形
System.out.println(StringUtils.isBlank(str)); // true

str = null;
System.out.println(StringUtils.isBlank(str)); // true
// 如果用 StringUtils.isNotBlank() <-- 則以上結果會相反
}

/**
* 1. Checks if a String is empty ("") or null. (判斷 string 是否是 "" 或 null, 與
* blank 的差別在於 whitespace )
*/
public static void demoEmpty() {
String str = " ";
System.out.println(StringUtils.isEmpty(str)); // false

str = " abc ";
System.out.println(StringUtils.isEmpty(str)); // false

str = " "; // 全形
System.out.println(StringUtils.isEmpty(str)); // false

str = null;
System.out.println(StringUtils.isEmpty(str)); // true
// 如果用 StringUtils.isNotEmpty() <--則以上結果會相反
}

/**
* 1. Compares two Strings, returning true if they are equal. (比較2個字串,
* 回傳是否相等) 2. nulls are handled without exceptions. (當 null 時, 不會發生
* exception) 3. Two null references are considered to be equal. (皆為 null 時,
* 則認為是相同的.) 4. The comparison is case sensitive. (大小寫有差別)
*/
public static void demoEquals() {
System.out.println(StringUtils.equals(null, null)); // true
System.out.println(StringUtils.equals(null, "abc")); // false
System.out.println(StringUtils.equals("abc", null)); // false
System.out.println(StringUtils.equals("abc", "abc")); // true
System.out.println(StringUtils.equals("abc", "ABC")); // false
}

/**
* 與 StringUtils.equals 的差別在於呼略大小寫
*/
public static void demoEqualsIgnoreCase() {
System.out.println(StringUtils.equalsIgnoreCase(null, null)); // true
System.out.println(StringUtils.equalsIgnoreCase(null, "abc")); // false
System.out.println(StringUtils.equalsIgnoreCase("abc", null)); // false
System.out.println(StringUtils.equalsIgnoreCase("abc", "abc")); // true
System.out.println(StringUtils.equalsIgnoreCase("abc", "ABC")); // true
}

public static void main(String[] args) {
System.out.println("Demo StringUtils.isBlank ---");
demoBlank();

System.out.println("\n\nDemo StringUtils.isEmpty ---");
demoEmpty();

System.out.println("\n\nDemo StringUtils.equals ---");
demoEquals();

System.out.println("\n\nDemo StringUtils.equalsIgnoreCase ---");
demoEqualsIgnoreCase();

}
}


還有太多好用的 method 了, 如: trim, substring, replace, isNumeric ... 等, 要記得去看 api ^_^.
結論 :
使用 StringUtils 可以減少錯誤的發生, 也可以少寫一些 code @@, 當然, 他的速度並不會比較慢唷, 如果跟自己寫來比的話, 能用就用吧 ^^, 如果你基礎有打好的話, 用一些別人寫的好來開發, 或許是個不錯的選擇.

2009年8月12日 星期三

Design Pattern - Template Pattern

Template Pattern

通常, 共用的方法, 我們可能會在父類別先實作, 不同的部份再定義成抽象, 由子類去實作

而Template Pattern只是告訴我們, 這些由子類別去實作的方法, 若也能抽象化呢?

舉個例子:
coco飲料店要做一杯飲料, 其中addWater(), putCup()是共用的
prepareRecipt()可以定成抽象, 各個飲料不同之處去實作


public abstract class CocoBeverage{

//boilWater(), pourlnCup(), 是共用的方法
public void addWater(){
//實作
}
public void putCup(){
//實作
}
public abstract void prepareRecipt();
}

public class MilkTea extends CocoBeverage{

public void prepareRecipt(){
addMilk();
}
public void addMilk(){
...
}
}

public class LemonTea extends CocoBeverage{

//略
public void addLemon(){
...
}
}


Template Pattern 說明, 可以提供一個公開方法, 定義出執行的步驟, 而怎麼實作可交由子類負責

所以, 上面的addMilk(), addLemon(), 其實很相同, 若能以 addCondiment統一命名, 來把這步驟抽象化呢?


public abstract class CocoBeverage{

public void addWater(){
...
}
public void putCup(){
...
}
final void executeBeverage(){ //final 注意, 不希望被繼承

addWater();
addCondiment();
putCup();
}

public abstract void addCondiment();
}

public class MilkTea extends CocoBeverage{

public void addCondiment(){
//實作加入milk
}
}

public class LemonTea extends CocoBeverage{

public void addCondiment(){
//實作加入lemon
}
}


所以我們只要去使用CocoBeverage 提供的 executeBeverage, 就可做飲料
提供抽象的CocoBeverage類別, 就是要減少client在使用時, 只依賴這class, 而不要與未來會實作的class有關聯(可以一直增加飲料種類)

--

補充1:
我們是不是可以在 executeBeverage(), 提供的template methed命名上, 加上Impl呢?
executeBeverageImpl()或templateExecuteBeverage()呢? 如此更可以讓別人一看就知用途


補充2:
Design Pattern 一書中, 提到一種勾子的模式, hook()

若我們在抽象CocoBeverage的template method中, 加入一個只宣告, 但不做事的空方法呢?

若有這hook()的存在, 可以讓子類別對template的步驟中, 不同點進行掛勾, 讓這些步驟有可能進行修改, 當然要不要勾, 由子類決定

同上, 做點修改

public abstract class CocoBeverage{
...略
final void executeBeverage(){

addWater();
if(hook()){ //預設一定會加調味料
addCondiment();
}
putCup();
}

public abstract void addCondiment();

public boolean hook(){ 這就是一個勾子, 子類別可以override, 以控制這template的步驟
return true;
}
}


我覺 hook()只是一種講法, 實現的情況會很多種, 所以還是要認清, pattern不是死的, 只是為了學習更好的寫法


補充3:
實作時, 要去繼承abstract的class這種方式, 彈性不夠
書上有舉例, 平時要排序時, 要去implements Comparable介面的compareTo(), 也是一種template pattern的實作
當要排序時, Collection.sort(Object o); 可以把這sort()想成template, 反正我們不用管sort()怎麼做的,
而且sort就是有固定的步驟, 且實現可由子類別控制,
只要我們把要排的object丟進去就好, Comparable介面就是讓我們控制的一個hook()

2009年8月11日 星期二

Configuration

Java 中有個好用的物件, Properties, 可以將常常會修改的資料存在這裡 (file) , 通常會以 .properties 結尾, 也可以用 xml 檔案.

每次要使用時, 必須寫一堆 code :

package hank.jakarta.common.configuration;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class ConfigurationTest {

public static final Log log = LogFactory.getLog(ConfigurationTest.class);
public static final String propName = "mmmm.properties";

private String name;
private String working;

private Properties prop;

private ConfigurationTest() {
// do something
try {
initProp();
} catch (IOException e) {
log.error(e.getMessage(), e);
}
}

private static class SingletonHolder {
private static final ConfigurationTest instance = new ConfigurationTest();
}

public static ConfigurationTest getInstance() {
return SingletonHolder.instance;
}

private void initProp() throws IOException {
if (prop == null) {
prop = new Properties();
String realPath = getClass().getClassLoader().getResource(propName)
.getPath();
File f = new File(realPath);
if (!f.isFile()) {
throw new FileNotFoundException("path not found!! : " + realPath);
} else {
prop.load(new FileInputStream(f));
// load properties ......
setName(prop.getProperty("name"));
setWorking(prop.getProperty("working"));
}
}
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getWorking() {
return working;
}

public void setWorking(String working) {
this.working = working;
}

public static void main(String[] args) {
// test
ConfigurationTest config = ConfigurationTest.getInstance();
System.out.println(config.getName());
System.out.println(config.getWorking());
}
}



來看看紅色的地方, 每當使用時 (假設檔案是放在 classes 裡), 必須自己經過一些處理後, 再把變數都 setter 好, 才能使用. 這種是一般最常件的方法.

昨天在 surfing jakarta website 時, 看到一個好用的 tool - Jakarta commons-configuration
把一堆 code 都封裝了起來, 我們要用使就變得特別方便, 也可以設定他動態 reload 的方式.


package hank.jakarta.common.configuration;


import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class ConfigurationTest1 {

public static final Log log = LogFactory.getLog(ConfigurationTest1.class);
public static final String propName = "mmmm.properties";

private String name;
private String working;

private PropertiesConfiguration prop;

private ConfigurationTest1() {
// do something
try {
initProp();
} catch (ConfigurationException e) {
log.error(e.getMessage(), e);
}
}

private static class SingletonHolder {
private static final ConfigurationTest1 instance = new ConfigurationTest1();
}

public static ConfigurationTest1 getInstance() {
return SingletonHolder.instance;
}

private void initProp() throws ConfigurationException {
if (prop == null) {
prop = new PropertiesConfiguration(propName);
}
// load properties ......
// String
setName(prop.getString("name"));
setWorking(prop.getString("working"));
// 如果是 double, 可以這樣寫, 就會幫你轉好了.
// prop.getDouble("double");

// 其它像 integer, ...都是.

// 那如何動態 reload 呢?, 其實很簡單
prop.setReloadingStrategy(new FileChangedReloadingStrategy());

// FileChangedReloadingStrategy <-- 這個是指, 當你修改了 attribute 時, 下一次去存取時, 會先去檢查最後修改日期, 來判斷他是否有修改, 如果有, 就 reaload.

}


public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getWorking() {
return working;
}

public void setWorking(String working) {
this.working = working;
}

public static void main(String[] args) {
ConfigurationTest1 config = ConfigurationTest1.getInstance();
System.out.println(config.getName());
System.out.println(config.getWorking());
}
}



今天先分享到這. 打球囉.

Quartz - 時間設定範例

 
Seconds 0-59 , - * /
Minutes 0-59 , - * /
Hours 0-23 , - * /
Day-of-month 1-31 , - * ? / L W
Month 1-12 or JAN-DEC , - * /
Day-of-Week 1-7 or SUN-SAT , - * ? / L #
Year (Optional) empty, 1970-2099 , - * /

'?' - It is used to specify 'no specific value'. (used in Day-of-month, Day-of-Week only)
This is useful when you need to specify something in one of the two fields, but not the other.


以上是官方文件

範例:感謝小胖提供XD

1.每5秒
/5 * * * *
2.每5分
* /5 * * *



未完...

在<a href></a> 中新增屬性

以下是一般的用法 :

<a href="http://mmmmtodd.blogger.com/">學海無涯<a>


假如想要在 href 中新增一個屬性 "to", 裡面放的是超連結的位置, 可以這樣做 :

HTML


<span id="myHref">
<a href="javascript:void(0);" to="http://tw.yahoo.com/">yahoo<a>
<a href="javascript:void(0);" to="http://www.google.com.tw/">google<a>
</span>


JQuery

var myHref = $("#myHref a");
myHref.click(function() {
var to = $(this).attr("to");
alert(to);
// do something , ex: window.location.href=to
});

2009年8月10日 星期一

css style 位置對不齊

css style 位置對不齊


若有在網頁中宣告時

!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"

height與width必須符合w3的規定,加上px
div name=item id=item style=position:relative;visibility:;height:250px;width:300px



感謝董哥分享

2009年8月7日 星期五

Design Pattern - Adapter Pattern

Adapter Pattern

看了良葛格詳細的說明, 原來pattern還是有區別用途
gof模式
Creational 模式
Structural 模式
Behavioral 模式

這裡提到的Adapter Pattern 屬於 Structural 模式, 是如何設計物件之間的靜態結構的一個解決方案

Adapter Pattern 有分為 Object Adapter 與 Class Adapter
而 Class Adapter是要運用在多重繼承上的, java不行直接多重繼承, 這裡不提

Adapter Pattern 與 Decorator Pattern 類似, 都是要把一些物件封裝起來

當你想銜接二個不同的接口時, 可以考慮這模式, 例如:

原本開發時, 假設client端(這裡假設程式是提供給別人用, 不能輕易的改code),
在實作時, 要取得客戶資料時, 都是對應到ICustomer介面,
但後來想要增加經銷商處理的功能時...

public interface ICustomer{
public String sync();
public String save();
}


實作客戶取資料的動作

public class Customer implements ICustomer{

public String sync(){
//客戶資料的同步
}
public String save(){
//客戶資料儲存
}
}


假設這個類別是提供給客戶使用的

public class BusinessLogic{

ICustomer customer;
Public BusinessLogic(ICustomer customer){
this.customer = customer;
}

public void syncCustomer(){
customer.sync();
}
public void saveCustomer(){
customer.save();
}
}


客戶實際操作商業邏輯時

public class DemoClients{
public static void main(String[] args){
//logic
Customer c = new Customer(); //要處理customer資料時
BusinessLogic bl = new BusinessLogic(c);
bl.syncCustomer();
bl.saveCustomer();
}
}


但現在突然想加入經銷商的一些處理時, 但要處理的動作與ICustomer不同時,
可以寫個Adapter來中介


public interface IDealer{
public String buildXML();
public String save();
}

public class Dealer implements IDealer{
public String buildXML(){
//經銷商的實作xml
}
public String save(){
//經銷商的實作save
}
}


這裡是implemnts 原本的ICustomer介面, 所以對提供給user的BusinessLogic介面是相同的

public class DealerAdapter implements ICustomer{

private Dealer dealer;

public dealerAdapter(IDealer dealer){
this.dealer = dealer;
}

public String sync(){
dealer.sync();
}
public String save(){
dealer.save();
}
}


所以現在提供給user的BusinessLogic class不用動, 就可以加點東西

public class DemoNewClients{

public static void main(String[] args){

//logic
Customer c = new Customer(); //要處理customer資料時
BusinessLogic bl = new BusinessLogic(c);
bl.syncCustomer();
bl.saveCustomer();

//logic
Dealer dealer = new Dealer(); //當要處理dealer的資料時
DealerAdapter dealerAdapter = new DealerAdapter(dealer);
BusinessLogic bl = new BusinessLogic(dealerAdapter);
bl.syncCustomer(); //對user來講, 使用的接口是相同的, 但行為變了
bl.saveCustomer();
}
}

2009年8月6日 星期四

lucene2.4 - Query

1.WildcardQuery支援萬用字元 * , ?

WildcardQuery wq1 = new WildcardQuery(new Term("id", "*hank*"));
WildcardQuery wq2 = new WildcardQuery(new Term("id", "*todd*"));
bq = new BooleanQuery();
bq.add(wq1, Occur.SHOULD);
bq.add(wq2, Occur.SHOULD);
query = bq;


但使用萬用字元,會丟TooManyClauses的exception

org.apache.lucene.search.BooleanQuery$TooManyClauses: maxClauseCount is set to 1024


/** Set the maximum number of clauses permitted per BooleanQuery.
* Default value is 1024.
*

TermQuery clauses are generated from for example prefix queries and
* fuzzy queries. Each TermQuery needs some buffer space during search,
* so this parameter indirectly controls the maximum buffer requirements for
* query search.
*

When this parameter becomes a bottleneck for a Query one can use a
* Filter. For example instead of a {@link RangeQuery} one can use a
* {@link RangeFilter}.
*

Normally the buffers are allocated by the JVM. When using for example
* {@link org.apache.lucene.store.MMapDirectory} the buffering is left to
* the operating system.
*/

2009年8月5日 星期三

Design Pattern - Command Pattern

Command Pattern

可將請求的動作與執行的動作分開

若假設現在的需求是要提供api給user使用時, 當然api會一直增加時

假設我們, 把使用者基本資料 封裝成 member object
api object用來封裝請求的資料, user不用管如何取得資料, 只要call execute()

整個Command Pattern可以想成有下列幾個角色
Client class --> createCommandObject() //要用的人就new object
Command class --> setCommand() //設定要使用那個命令
Invoker class --> execute() --> Command class //調用者會就去執行execute
Command class --> Receiver class //執行動作


宣告一個要執行命令的接口

public interface ICommand{
public String execute();
//public String executeXML(); //也可吐xml回去
}


實現取得客戶資料的命令 --> 注意這裡是指命令, 這裡就是把某個請求封裝起來

public class CustomerCommand implements ICommand{

Customer customer;

public CustomerCommand(Customer customer){
this.customer = customer;
}

public String execute(){
customer.getDB();
String result = customer.setXML();
return result;
}
}
public class EmployeeCommand implements Icommand(){ ... }

//實作如何取得資料, 並轉成xml
public class Customer{
getDB();
setXML();
...
}
public class Employee{ ... }


上面的 CustomerCommand class 與 Customer class就是把請求與執行分開來了

再來做一個統一對外執行的介面, 以後若有增加新的api, 這class是不需修改的,
這class 是上面提到的invoker角色(調用者)


public class APIControl(){

Command command;

public APIControl(){}

public void setCommand(Command command){
this.command = command;
}

public String doExecute(){
return command.execute();
}
}

public class DemoCallAPIP{

public static void main(String[] args){
APIControl api = new APIControl();
Customer customer = new Customer();
CustomerCommand customerCommand = new customer(customer);

api.setCommand(customerCommand); //傳入要執行的命令
String xmlResult = api.doExecute(); //就執行囉
}
}

2009年8月4日 星期二

正規表示式-regex-取出中文字

如果想要找出中文字, 可以使用 regex 對中文unicode的支援.


public static void main(String[] args) {
String oriStr = "我是小胖123444#$%^*(";
String afterStr = getChinese(oriStr);
System.out.println(afterStr); // 顯示 "我是小胖"
}
public static String getChinese(String in) {
if (in == null || ("".equals(in))) {
return "";
}
Matcher matcher = Pattern.compile("\\p{InCJKUnifiedIdeographs}").matcher(in);
StringBuffer out = new StringBuffer();
while (matcher.find()) {
out.append(matcher.group());
}
return out.toString();
}


這邊要解釋「\\p{InCJKUnifiedIdeographs}」:
在 Unicode 中,有針對各個編碼區塊做分類,它的列表可以參照下面的檔名:

Unicode 3.2 的列表:
http://www.unicode.org/Public/3.2-Update/Blocks-3.2.0.txt

Unicode 4.1.0 的列表:
http://www.unicode.org/Public/4.1.0/ucd/Blocks.txt

Unicode 5.0 的列表
http://www.unicode.org/Public/5.0.0/ucd/Blocks.txt

這個表裡面列出了統一碼區塊名和相對應的 Unicode 區段,
而其中的「CJK Unified Ideographs」就是我們的中文字區段(看名稱,應該包含日文、簡體、韓文),
而在 RegEx 中,可以透過「\p」來指定這個統一碼區塊名,
透過指定它,找出相對應的文字範圍,Java 就是這樣做的。

相關文章 : http://developers.sun.com/dev/gadc/unicode/perl/perl561.html