Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android四種常見設計模式說明

Android四種常見設計模式說明

編輯:關於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 List list=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實例,模擬一個用戶繼續替你完成打官司的事情。
篇幅有限,設計模式有很多種,以上列舉了常用的幾種,也是最常用最基礎的幾種,希望大家能夠理解並掌握,如有興趣,請參考《設計模式之禅》這本書,個人覺得不錯。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved