開篇廢話
入職后一直研究Android framework的東西,大概花了一個月鼓搗了一個系統應用“應用雙開”。雖然也是敲代碼,但是主要是在Android源碼中進行修改,也可以說很久沒用java去寫一個完整的東西了。近來公司有個小工具需要開發,上頭應該覺得功能很簡單,所以讓我一個人開發。具體功能需求不便透露,主要是一個windows應用。本來我打算用C#寫,但是老大說最好用java,最終選了java swing來開發。這是一個很古老的東西,反正我也不熟悉,在大概學習了swing的組件使用之后,就開始動手coding了。
java思想
其實不管java也好,其他面向對象語言也好。面向對象的思想就是分工而治,統一管理。這里我就不吹逼面向對象了,畢竟能力有限,吹逼能力有限,道行尚淺。大家記住這幾個字分工而治,統一管理。
例如
說一千道一萬,眼見為實耳聽為虛。我寫的工具中有這么一項需求。大致類似于,我要寫滿漢全席的食譜,總共一百零八道菜,每道菜都需要配圖(UI)和做法(文本),最終寫到一個冊子中(文本匯總)。
需求分析:
1.一百零八道菜,每個菜都不同,應該對應著有108個類吧。
2.每道菜都需要配圖和做法,對應著每個類都應該有一個pic()方法和cook()方法吧。
3.最終寫到一個冊子中。匯總:調用所有類的cook()方法,寫到一個文本中。
代碼設計
一定要記住,不要忙于寫代碼,而是搞清楚功能邏輯,不然寫到一半改需求是真的很要命,我就吃了這個虧,好在我前期代碼結構設計還算可以,不至于重頭來過。
言歸正傳:108道菜,每道菜都不同,如果沒有重樣的菜,就意味應該有108個類。每個類都有pic()和cook()方法,說明這是共用類,匯總的時候去調用每個類的cook()方法。
按照道理講功能的邏輯是這樣沒錯了,如果這108類每個類都不一樣的話,這108類看來是必不可少了,pic()和cook(),屬于類的方法,無可厚非,但是匯總時,我總不能把每個類都實例化一遍然后去調用各自的cook方法吧。所以這時候,java的抽象類和接口就得派上用場了。抽象類和接口都是用于類的繼承,抽象類只能單繼承,接口可以多繼承,這些基礎的概念,想必大家都懂,不懂沒關系,可以上網去查啊http://www.lxweimin.com/p/038f0b356e9a,
但是值得去講的是:抽象類和接口中都是抽象方法,就是沒有實現的方法,語法上支持你去調用這個方法,但是最終調用的是繼承了該類或接口并實現了該方法的類。
所以:我們可以這樣做,這些如何靈活運行接口和抽象類就看各自的本事了,我大致講解一下我的做法。
首先我定義了一個抽象類
public abstract class Food {
public String type = "";
public Food() {
}
abstract public String cook();
abstract public void pic();
}
其中有兩個未實現的抽象方法,因為考慮到108到菜也分菜系,所以用了type變量用來標識菜系。
現在我們要做兩個菜系的菜,粵菜,和川菜。不管他們是哪個菜系,但是他們都屬于food,于是就呈現出一種繼承關系。
然后定義粵菜類和川菜類:
public abstract class YueCai extends Food {
public YueCai() {
type = "YueCai";
}
}
public abstract class ChuanCai extends Food {
public ChuanCai() {
type = "ChuanCai";
}
}
因為他們是food類的子類,所以他們也含有food類的pic()和cook()方法。
既然要寫成菜譜,那么我們是否應該有一個專門來寫菜譜的人。
接著我們來定義cooker類
import java.util.List;
public class Cooker {
private List<Food> foods = null;
public Cooker() {
}
public void addFood(Food food) {
foods.add(food);
}
public void write() {
StringBuffer cookBook = new StringBuffer();
for(Food food : foods) {
cookBook.append(food.cook());
}
}
}
這里的cooker類,就是統一管理的類,首先是維護了一個List,類型是Food類,Food是抽象類,就是告訴大家,我這里要裝的菜肴,但具體是什么菜,你實際放什么菜那就是什么菜,我這里不關心。
然后定義了add方法,用于往List中填充內容,write()函數,就是寫菜譜了,循環遍歷List<Food>,依次調用Food的cook方法。這里就解決了,108道,每道菜不同,不需要我分別調用這108個類的方法,因為我在這里統一調用了抽象類Food的抽象方法cook(),但是這個方法是未實現的方法,所以它最終調用的是實現了這個方法的類。那么到底哪個類實現了該方法,而又是如何才能調用到的呢。
上面寫的所有的類都是代碼結構的搭建,說白了就是一群只知道說,不去做事的家伙
那么我們來定義踏實干活的人吧
public class MapoDouFu extends ChuanCai{
public MapoDouFu() {
}
@Override
public String cook() {
return "mapoDoufu";
}
@Override
public void pic() {
}
}
public class YanjuChicken extends YueCai {
public YanjuChicken() {
}
@Override
public String cook() {
return "YanjuChicken";
}
@Override
public void pic() {
}
}
我們這里定義了兩道菜的類,一個MapoDoufu,一個YanjuChicken。他們分別繼承了ChuanCai類和YueCai類,而ChuanCai類和YueCai類都是繼承自Food類,所以他們都是Food類的子類。并且都是Food類的最終實現類。
然后我們在合適的地方去調用Cooker的addFood()方法
Cooker cooker = new Cooker();
MapoDouFu mapoDouFu = new MapoDouFu();
cooker.addFood(mapoDouFu);
YanjuChicken yanjuChicken = new YanjuChicken();
cooker.addFood(yanjuChicken);
這里就是java多態的體現,我們定義addFood()方法時,形式參數是Food類,但是在調用時實際傳入的Food類的子類MapoDoufu和YanjuChicken類。所以當我們去調用wirte()時,也將調用的實際傳入類的cook()方法。
這是簡單的對抽象類一個應用場景的介紹,同樣,接口也是可以這樣使用的。原理是一樣的,我這里就不復述了。
public interface Food {
public void pic();
public String cook();
}
public class YanjuChicken implements Food {
public YanjuChicken() {
}
@Override
public void pic() {
}
@Override
public String cook() {
return "YanjuChicken";
}
}
public class MapoDoufu implements Food {
public MapoDoufu() {
}
@Override
public void pic() {
}
@Override
public String cook() {
return "MapoDoufu";
}
public class Cooker {
private List<Food> foods = null;
public Cooker() {
}
public void write() {
StringBuffer cookBook = new StringBuffer();
for(Food food : foods) {
cookBook.append(food.cook());
}
}
public void addFood(Food food) {
foods.add(food);
}
}
至于type的作用,本篇沒有體現出來,而是想告訴大家要有抽象分類的思想。