編輯:關於android開發
前言:
Android開發的設計模式,基本設計思想源於java的設計模式,java的設計模式有N多種,據不完全統計,迄今為止,網絡出現最頻繁的大概有23種。Java只是一門開發語言,學會並掌握這門語言進行代碼編寫,這是每個程序員必修的課程,但如何寫出高質量、易維護和復用性強的代碼,那就體現出程序員的層次和水平了。設計模式的出現就是為了解決這些問題。
開始學習設計模式的時候,我們通常都有種將簡單問題復雜化的感覺,明明一個類N行代碼就能完成的事情,干嘛非要創建幾個類?又抽象又難理解的。後來隨著開發經驗的增長,重復勞動的頻繁,終有一天頓悟,體驗到設計模式的妙用,方感慨萬千。常言,水滴石穿,做任何事都是這樣,經驗和時間是最好的試金石。
1.工廠模式:
什麼是工廠模式?比如公司有個這樣一個需求,在App中要使用到LBS定位來實現某些功能。產品技術一大堆開始了需求、技術確認會,當大家討論到定位是用百度API來實現,還是用高德來實現。大家爭論不休,有人說百度定位不准,有人說高德定位不准,眾說紛纭。咋辦?最後,B總拍板,兩個一起用,哪個好用哪個,領導拍板了,但說了又等於沒說,咋辦?工廠模式這時候就呼之欲出了,我兩個都給你設計,代碼設個開關和參數,你說用高德不爽,我改個參數,就換百度,直到領導高興為止,於是代碼就產生了。
public class test { public static void main(String[] args) { Location position= new LocationFactory().getInstance("gaode"); position.getPosition(); position.getCityName(10, 20); } } class LocationFactory{ public static Location getInstance(String type){ if("baidu".equals(type)){ return new BaiduLocation(); }else { return new GaodeLocation(); } } } class BaiduLocation implements Location{ @Override public void getPosition() { // TODO Auto-generated method stub System.out.println("通過百度定位獲取到當前的經緯度是XXXXX"); } @Override public void getCityName(long lat, long lng) { // TODO Auto-generated method stub System.out.println("通過百度定位獲取到當前的城市是XXXXX"); } } class GaodeLocation implements Location{ @Override public void getPosition() { // TODO Auto-generated method stub System.out.println("通過高德定位獲取到當前的經緯度是XXXXX"); } @Override public void getCityName(long lat, long lng) { // TODO Auto-generated method stub System.out.println("通過高德定位獲取到當前的城市是XXXXX"); } } interface Location{ public void getPosition(); public void getCityName(long lat,long lng); }
上面的例子,較好的闡述了工廠模式的概念。LocationFactory是一個工廠類,靜態函數getInstance的參數決定了是選用百度還是高德,這樣,對於調用者來說,只需要關心你是用百度還是高德即可。Location是一個接口,它抽象出高德和百度常用的函數調用。拿定位來說,基本上常用的就是根據經緯度查詢地址,或者定位當前所在位置獲取經緯度。當然可能還有更多有用的函數,我這裡就不在列舉。有了這樣一個共性的接口,GaodeLocation和BaiduLocation通過實現它的接口就能分別滿足調用者的需求。調用者就能夠任意通過改變參數,來實現來自不同定位API的需求。當然,如果百度和高德不爽,你完全可以使用谷歌API,只需要構造一個GoogleLocation類並實現Location接口的方法即可。
工廠模式的應用非常廣泛,比如android的bitmap中常用的BitmapFactory類,創建Bitmap對象,通常使用靜態工廠方法。
2.單例模式:
什麼是單例模式?單例模式的精髓主要在這個“單”字上,“單”就是一個,直接進入主題,我們通常使用“new”關鍵字創建一個對象,一旦“new”了,它就會開辟內存創建一個對象。假設我們經常反復創建的這個對象對我們來說其實都是一回事,那麼我們就沒必要浪費資源和時間嘛,好比,你去外地出差在某個地方至少1天,第一次你去服務台,服務台給你開了間房,你高高興興的拿著鑰匙進房睡覺了。睡醒後出去辦事。完事後,你是不是直接拿著這個鑰匙直接奔你開好的房間?該不會去服務台再去開一間吧?大道至簡,其實,細細想來,生活就是一種模式,只要你善於發現,你就會有意外驚喜,原來都是這樣簡單。
來個例子吧,枯燥的代碼。
public class Room { public static Room key; public static void main(String[] args) { Room room=getKey(); room.openDoor(); Room room1=getKey(); room1.openDoor(); } public static Room getKey(){ if(key==null){ key=new Room(); } return key; } public void openDoor(){ System.out.println("我打開了門......"); } }
看看上面這個例子,是不是跟我舉得賓館的例子相似?這樣做,既節約了賓館的時間,也節約了你的時間,多好啊。再引申一點說,android開發中也常常使用到單例模式,比如網絡的封裝,數據庫的訪問都用到了單利的設計模式。
3.觀察者模式:
什麼是觀察者模式?一般提到原告,必然腦子立刻聯想到被告,觀察者和被觀察者就如同原告和被告總是那麼成對出現。觀察者模式,又被叫做訂閱模式,有訂閱者和發布者。當下IPHONE6異常火爆,國內粉絲要想購買,那必須得預定,必須到它蘋果官方去預定,填一大堆資料,交不交錢我不知道,反正得預定登記。等粉絲等到兩眼欲穿、花兒快謝了時候,它粉墨登場了,官方以高姿態從容向預定過的粉絲發售。這蘋果就是被觀察者,粉絲就是觀察者,觀察者和被觀察者之間需要建立聯系,那就是登記。登記過後,被觀察者拿捏火候覺得時機成熟的時候,就以權位者姿態向觀察者拋出繡球,觀察者迫不及待的伸出雙手牢牢抓住後,滿心歡喜的贊美蘋果的偉大和自己的慶幸。睜大眼睛盯著目標看,期待期望結果,這就是觀察者模式。
來段代碼體驗
import java.util.ArrayList; import java.util.List; public class MyOberver { public static void main(String[] args) { American american=new American(); Chinese chinese=new Chinese(); Iphone iphone=new Iphone(); System.out.println("一個美國人登記購買"); iphone.register(american); System.out.println("一個中國人登記購買"); iphone.register(chinese); try { System.out.println("經過6個月的漫長等待..."); Thread.sleep(2000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } iphone.notifys(); } } /**觀察者*/ class Iphone{ private Listlist=new ArrayList (); public void register(Fensi n){ list.add(n); System.out.println("又一個蘋果被預訂了,現在總共有:"+list.size()+"個人預訂了..."); } public void notifys(){ System.out.println("IPHONE 6現在高調發售..."); for (Fensi n:list) { n.receive(); } } } class American implements Fensi{ @Override public void receive() { // TODO Auto-generated method stub System.out.println("美國人喊叫:嗯哼,有點貴...."); } } class Chinese implements Fensi{ @Override public void receive() { // TODO Auto-generated method stub System.out.println("中國人:我終於買到了,高興死了...."); } } interface Fensi{ public void receive(); }
運行後輸出結果:
一個美國人登記購買
又一個蘋果被預訂了,現在總共有:1個人預訂了...
一個中國人登記購買
又一個蘋果被預訂了,現在總共有:2個人預訂了...
經過6個月的漫長等待...
IPHONE 6現在高調發售...
美國人喊叫:嗯哼,有點貴....
中國人:我終於買到了,高興死了....
這就是觀察者模式,Chinese和American都是觀察者,它們繼承了Fensi接口,具有了接收消息receive的能力,Iphone是被觀察者,是被觀察的目標,它的一舉一動,都會深深的影響Fensi們的熱情,觀察者需要在被觀察者哪裡進行登記購買register,登記過後,等到時機成熟了,被觀察者會主動放出信號iphone.notifys();這樣,凡是登記過購買蘋果6的粉絲們,都會紛紛收到取貨的信息了。
4.代理模式:
什麼是代理模式?代理模式在各類開發中運用的相當廣泛,不論是j2ee,android還是ios,都能看到它的身影,所以說設計模式無處不在。代理模式,字面理解就是自己不方便做或者不能做的事情,需要第三方代替來做,最終通過第三方來達到自己想要的目的或效果。舉例了:員工小李在B總公司打工,B總成天讓小李加班不給加班費,小李忍受不住了,就想去法院告B總。雖然法律上允許打官司不請律師,允許自辯。但是小李第一不熟悉法律起訴的具體流程,第二嘴比較笨,人一多腿就抖得厲害。因此,小李決定去找律師幫忙打官司。找律師打官司和自己打官司相比,有相同的地方,也有不同的地方。
相同的地方在於:
1、 都需要提交原告的資料,如姓名、年齡、事情緣由、想達到的目的。
2、 都需要經過法院的取證調查,開庭爭辯等過程。
3、 最後拿到審判結果。
不同地方在於:
1、 小李省事了,讓專業的人做專業的事,不需要自己再去了解法院那一套繁瑣復雜的流程。
2、 把握更大了。
通過上面的例子,我們注意到代理模式有幾個重點。
1、 被代理的角色(小李)
2、 代理角色(律師)
3、 協議(不管是代理和被代理誰去做,都需要做的事情,抽象出來就是協議)
下面給個例子:
public class Proxy { public static void main(String[] args) { Employer employer=new Employer(); System.out.println("我受不了了,我要打官司告老板"); System.out.println("找律師解決一下吧......"); Protocol lawyerProxy=new LawyerProxy(employer); lawyerProxy.register("朵朵花開"); lawyerProxy.dosomething(); lawyerProxy.notifys(); } } interface Protocol{ //登記資料 public void register(String name); //調查案情,打官司 public void dosomething(); //官司完成,通知雇主 public void notifys(); } //律師類 class LawyerProxy implements Protocol{ private Employer employer; public LawyerProxy(Employer employer){ this.employer=employer; } @Override public void register(String name) { // TODO Auto-generated method stub this.employer.register(name); } public void collectInfo(){ System.out.println("作為律師,我需要根據雇主提供的資料,整理與調查,給法院寫出書面文字,並提供證據。"); } @Override public void dosomething() { // TODO Auto-generated method stub collectInfo(); this.employer.dosomething(); finish(); } public void finish(){ System.out.println("本次官司打完了..............."); } @Override public void notifys() { // TODO Auto-generated method stub this.employer.notifys(); } } //雇主類 class Employer implements Protocol{ String name=null; @Override public void register(String name) { // TODO Auto-generated method stub this.name=name; } @Override public void dosomething() { // TODO Auto-generated method stub System.out.println("我是'"+this.name+"'要告B總,他每天讓我不停的加班,還沒有加班費。"); } @Override public void notifys() { // TODO Auto-generated method stub System.out.println("法院裁定,官司贏了,B總需要賠償10萬元精神補償費。"); } }
運行後,打印如下:
我受不了了,我要打官司告老板
找律師解決一下吧......
作為律師,我需要根據雇主提供的資料,整理與調查,給法院寫出書面文字,並提供證據。
我是'朵朵花開'要告B總,他每天讓我不停的加班,還沒有加班費。
本次官司打完了...............
法院裁定,官司贏了,B總需要賠償10萬元精神補償費。
代碼說明:
Protocol這個類就是上面所說的協議,是被代理者或者代理者共同遵守的約定。也就是說,無論是原告還是代理律師,到法院走程序,都需要做的事情。我們抽象出來,這個就是協議。
Employer這類是雇主類也稱被代理者類,它遵從Protocol協議,並實現了Protocol協議的三個方法,並去分別完成了具體事情。
LawyerProxy這類是代理類,它也遵從Protocol協議,與Employer不同的是,定義了一個Employer對象,通過構造函數初始化。在實現的三個方法裡,分別去調用被代理類的相同實現。就好比去模擬一個被告者,站在被告的角度上,去法院告狀。也就是說LawyerProxy代理類對所有想打官司的人開放,只要有原告進來,我就幫他打官司。值得注意的是collectInfo和finish這兩個函數,請律師打官司和不請律師打官司,其實都要做同樣的事情(register、dosomething、notifys),但是至於為什麼?剛才不是說了嗎,請律師的好處是省心並且專業,他在做同樣的事情前提下,還會收集對你有利的證據和資料(collectInfo),以及後續事情的處理(finish)。
上面就是最普通的代理模式,引申一點,我們看到,對於被告來說,必須創建一個Employer類,並實例化後傳參給LawyerProxy代理類,這樣做,是不是暴漏了Employer?如果隱藏一下,對於被告來說,更智能傻瓜一點,該怎麼做呢?
public class Proxy { public static void main(String[] args) { //Employer employer=new Employer(); System.out.println("我受不了了,我要打官司告老板"); System.out.println("找律師解決一下吧......"); Protocol lawyerProxy=new LawyerProxy("朵朵花開"); lawyerProxy.dosomething(); lawyerProxy.notifys(); } } interface Protocol{ //登記資料 public void register(String name); //調查案情,打官司 public void dosomething(); //官司完成,通知雇主 public void notifys(); } //律師類 class LawyerProxy implements Protocol{ private Employer employer; public LawyerProxy(String name){ if(name==null) { System.out.println("誰告狀?逗我玩呢吧?"); return; } if(employer==null) employer=new Employer(); register(name); } @Override public void register(String name) { // TODO Auto-generated method stub this.employer.register(name); } public void collectInfo(){ System.out.println("作為律師,我需要根據雇主提供的資料,整理與調查,給法院寫出書面文字,並提供證據。"); } @Override public void dosomething() { // TODO Auto-generated method stub collectInfo(); this.employer.dosomething(); finish(); } public void finish(){ System.out.println("本次官司打完了..............."); } @Override public void notifys() { // TODO Auto-generated method stub this.employer.notifys(); } } //雇主類 class Employer implements Protocol{ String name=null; @Override public void register(String name) { // TODO Auto-generated method stub this.name=name; } @Override public void dosomething() { // TODO Auto-generated method stub System.out.println("我是'"+this.name+"'要告B總,他每天讓我不停的加班,還沒有加班費。"); } @Override public void notifys() { // TODO Auto-generated method stub System.out.println("法院裁定,官司贏了,B總需要賠償10萬元精神補償費。"); } }
看到沒new LawyerProxy("朵朵花開"),只需要給代理類傳入簡單的名字,隱含了Employer類,代理類就會自動去創建一個Employer實例,模擬一個用戶繼續替你完成打官司的事情。
篇幅有限,設計模式有很多種,以上列舉了常用的幾種,也是最常用最基礎的幾種,希望大家能夠理解並掌握,如有興趣,請參考《設計模式之禅》這本書,個人覺得不錯。
Android Studio 打包apk,自動追加版本號和版本名稱 默認AS大包好的apk是app-deubg.apk的,這樣的話版本多了找出一個bug在哪個版本中存在的
Linux下超時重傳時間(RTO)的實現探究最近出現了網絡超時的問題要排查,大致按照如圖思路去排查1.排除代碼邏輯問題,TCP相關可能的BUG,內核參數等問題;2.排查K
Android 6.0: 動態權限管理的解決方案 Android 6.0版本(Api 23)推出了很多新的特性, 大幅提升了用戶體驗, 同時也為程序員帶來新的負擔. 動態
Tab標簽頁控件在很多編程技術中都能見到,它使得窗口顯示區能夠重復利用。在An