2016年12月27日 星期二

[Design Pattern]Strategy和泛型

【以下先是碎碎念...可以跳過不看。】

程式碼在概念上經常就只是「演算法」與「資料結構」的具體實現。

但在程式的整體「框架」上,很難從程式碼看出來整個程式的邏輯或概念。

除非大家都使用「演算法」來描述事情...但這不可能,實際上大家還是習慣用具體需求來描述事情,例如「怎麼找出特定檔案」。

但這件需求其實是種「快速比對檔案內容」的演算法,習慣上應該沒有人會用後者來描繪、形容、跟別人溝通,即使是工程師對工程師。(天知道有多少種演算法可以做到「找出特定檔案」這件事。)

所以Design Pattern被發明了!...(可以這樣理解吧?)

可是我發現很多人把DesignPattern當成一種程式碼設計的延伸,大家還是習慣用「具體需求」來理解「何時該使用哪種Pattern」。

【碎碎念完。】



Strategy這個Pattern對我來說是個優化、或簡化程式碼的好工具。

很多習慣函數式開發的工程師經常把程式搞成一大包,一支[.java]檔動輒上萬行是小事。這種程式碼難維護不說,擴充難度更是高。

碰到這種程式碼,一般來說我都會快速的將所有的函數一刀切成兩種:「有傳入參數」和「無傳入參數」兩種。(補充說明:還要先排除這些函數之間是同名異構的「覆載」函數。)

那些「無傳入參數」的函數基本上都是直接修改全域變數...所以就把所有非static型態的全域變數複製一份獨立成一個物件,先稱為「StrategyObj1」好了!(記得在原始程式中宣告一個StrategyObj1的實做物件。)

接著就可以將所有的「無傳入參數」的函數通通獨立出來實做成一個「內部不帶參數、只有函數」的物件/類別。


為什麼「無傳入參數」的函數會用「有傳入參數」的方式實做?

首先是為了方便未來擴充。

假設某功能需要使用者輸入資料一、資料二,例如居住地的縣市和詳細路段,但未來忽然需要擴充為兩組以上的地址,則只需要把資料一和資料二包裝成一個類別,然後宣告兩個物件並分別傳入對應的UI輸入結果,就可以繼續使用同一個Strategy物件函數來處理了。

其次...這可以延續物件導向的風格!

(未完)

2016年10月17日 星期一

[Codility] Training ticket -- 100%

Score 83
效能不合格....
// you can also use imports, for example:
// import java.util.*;

// you can write to stdout for debugging purposes, e.g.
// System.out.println("this is a debug message");

class Solution {
    public int solution(int[] A) {
        // write your code in Java SE 8
        
        int l = A.length;
        int l2 = A.length;
        
        for(int i = 0 ; i < l ;i++){
            int tmp = A[i];
            for(int j = i+1 ; j < l ;j++){
                
                if(A[j] == tmp){
                    i++;
                    A[j] += A[i];
                    A[i] = A[j] - A[i];
                    A[j] = A[j] - A[i];
                    l2--;
                }
                
            }
            
            
        }
        
        return l2;
    }
}

https://codility.com/demo/results/trainingYKSGPS-9KJ/


// you can also use imports, for example:
// import java.util.*;

// you can write to stdout for debugging purposes, e.g.
// System.out.println("this is a debug message");

class Solution {
    public int solution(int[] A) {
        // write your code in Java SE 8
        
        int l = A.length;
        
        for(int i = 1 ; i < l ;i++){
            for(int j = 0 ; j < i ;j++){
                
                if(A[i] == A[j]){
                    A[j] = 1000001;
                }
                if(A[j] == 1000001){
                    A[j] = A[i];
                    A[i] = 1000001;
                    
                    if(j > 0){
                        A[j-1] += A[j];
                        A[j] = A[j-1] - A[j];
                        A[j-1] = A[j-1] - A[j];
                    }
                    
                    
                    j = i;
                }
                
            }
            
        }
        
        for(int i = 0 ; i < l ;i++){
            if(A[i] == 1000001)
                return i;
        }
        
        return l;
        
    }
}

https://codility.com/demo/results/trainingZKNY6F-3GA/
成績沒有改善

// you can also use imports, for example:
// import java.util.*;

// you can write to stdout for debugging purposes, e.g.
// System.out.println("this is a debug message");

class Solution {
    public int solution(int[] A) {
        // write your code in Java SE 8
        
        int l = A.length;
        int count = 0;
        
        for(int i = 0 ; i < l ; i++){
            if(A[i] != 1000001){
                count++;
                for(int j = i+1; j < l ; j++){
                    if(A[j] == A[i]){
                        A[j] = 1000001;
                        if(j == l-1)
                            l--;
                    }
                }
                A[i] = 1000001;
            }
        }
        
        return count;
    }
}

https://codility.com/demo/results/training2H2FYZ-FT7/
依然沒有改善


// you can also use imports, for example:
// import java.util.*;

// you can write to stdout for debugging purposes, e.g.
// System.out.println("this is a debug message");

class Solution {
    public int solution(int[] A) {
        // write your code in Java SE 8
        
        int l = A.length;
        int count = 0;
        int[] A2 = new int[2000001];
        
        for(int i = 0 ; i < l ; i++){
            int tmp = A[i] + 1000000;
            if(A2[tmp] == 0)
                count++;
            A2[tmp]++;
        }
        
        return count;
        
        
    }
}
https://codility.com/demo/results/trainingCXSQ2W-JFG/
其實資料長度只有100000,並不算大!
直接計算出現次數就可以輕鬆解決效能問題!並不會造成記憶體不足的問題!
跟青蛙過河有異曲同工之妙!