2009年8月20日 星期四

Linux 常用指令

1.此目錄下有多少folder
ls -al wc -l

2.此目錄的總k數
du -h

3. awk 後計算加總 :
awk "BEGIN { sum = 0 } { sum += \$1 } END { print sum;}"

4.查詢所有目錄的容量
du -h --max-depth=1
du -hs /*
du -h

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);

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

正規表示式-regex-過滤 HTML Tags


// regex pattern
String filterPattern = "<[^>]+>";
Sring oriStr = "< b>我是小胖< /b>"

System.out.println(oriStr.replaceAll(fileterPattern, "");


// 如果 source 很長的話,
可以用 pattern & match 來處理, 才不會浪費 memory