隨筆-88  評(píng)論-77  文章-48  trackbacks-0
           
          1.Image格式文件轉(zhuǎn)成byte[]?

          答:第一步:
          如何獲得image對(duì)象的int數(shù)組呢?這個(gè)就簡(jiǎn)單了可以通過(guò)獲得RGB數(shù)組就可以。Image對(duì)象中有直接的getRGB方法,不過(guò)這里的參數(shù)的位置和J2SE中不太一樣
          第二步,把得到的Int數(shù)組再生成byte數(shù)組。
          原帖地址:http://www.j2medev.com/bbs/dispbbs.asp?boardID=2&ID=6559&page=1

          2.eclipse中RMS保存的文件在哪里?

          答:圖像文件保存的時(shí)候先轉(zhuǎn)化為byte[]?不是String?

          存儲(chǔ)的時(shí)候一般存儲(chǔ)為***.db文件??目錄在wtk_home/appdb/模擬器/***.db
          原帖地址:http://www.j2medev.com/bbs/dispbbs.asp?boardID=2&ID=6470&page=1


          3.關(guān)于播放midi

          答:須明確的一點(diǎn)是?我們的MIDlet是運(yùn)行在Java?ME平臺(tái)環(huán)境下的??不一定設(shè)備提供的功能在Java?ME平臺(tái)都得到了實(shí)現(xiàn)
          你可以將虛擬機(jī)可以播放的音樂(lè)類型!
          原帖地址:http://www.j2medev.com/bbs/dispbbs.asp?boardID=19&ID=6455&page=1


          4.團(tuán)隊(duì)開(kāi)發(fā)利器CVS培訓(xùn)基礎(chǔ)講義

          答:詳細(xì)見(jiàn):http://www.j2medev.com/bbs/dispbbs.asp?boardID=4&ID=6324&page=1


          5.netBean能用兩個(gè)代碼窗口顯示同一個(gè)類嗎?

          答:不能

          6.g.drawString()占用內(nèi)存問(wèn)題

          答:drawString()方法本身不占內(nèi)存,關(guān)鍵是drawString中的參數(shù)string是不是每次都new了一個(gè),如果把分?jǐn)?shù)變成圖片這樣就不會(huì)new新的對(duì)象,從而節(jié)省了內(nèi)存和gc的頻率。
          原帖地址:http://www.j2medev.com/bbs/dispbbs.asp?boardID=11&ID=5319&page=2

          7.手機(jī)上使用過(guò)三重的圖形緩沖技術(shù)

          答:三重圖形緩沖又稱翻頁(yè)技術(shù)。這種方法不一定會(huì)提高繪制速度,在J2SE中系統(tǒng)會(huì)根據(jù)速度在二重緩沖和該方法中自動(dòng)進(jìn)行切換,當(dāng)然僅僅是1.4版本以后添加的。一般的MIDP設(shè)備應(yīng)該會(huì)吃不消。
          原帖地址:http://www.j2medev.com/bbs/dispbbs.asp?boardID=11&ID=5376&page=2

          8.索愛(ài)k700模擬器支持中文顯示修改方法

          答:SonyEricsson_Z520.properties和SonyEricsson_K700.properties的不同點(diǎn),發(fā)現(xiàn)只是
          font.default?=?.......這塊字體屬性不一樣而已,因此就將k700所需的字體換成z520用的字體,就能顯示中文了。
          原帖地址:http://www.j2medev.com/bbs/dispbbs.asp?boardID=4&ID=3061&page=2

          9.模擬核彈的爆炸效果

          答:具體實(shí)現(xiàn)依賴于程序結(jié)構(gòu),原理就是顯示一張圖片后,循環(huán)一定次數(shù)才顯示下一張圖片。
          原帖地址:http://www.j2medev.com/bbs/dispbbs.asp?boardID=11&ID=6182&page=2

          10.UI界面和CANVAS類之間如何切換屏幕?

          答:在Canvas的paint()方法中把屏幕清一下???比如用白色覆蓋一下
          原帖地址:http://www.j2medev.com/bbs/dispbbs.asp?boardID=19&ID=1413&page=1

          11.關(guān)于?properties文件

          答:用UE或者notepad應(yīng)該都可以打開(kāi),這個(gè)文件是用來(lái)配置模擬器的特性的?比如是否支持觸摸屏。
          原帖地址:http://www.j2medev.com/bbs/dispbbs.asp?boardID=2&ID=6524&page=1

          12.在E680I中如何實(shí)現(xiàn)全屏

          答:在midp2.0下,摩托羅拉的機(jī)子也是可以用Canvas.setFullScreenMode()來(lái)全屏的,最上面的電池格以及信號(hào)強(qiáng)弱格那一窄條是固定的。而Nokia和索愛(ài)就不這樣,全屏真的是全屏。(不過(guò)經(jīng)過(guò)斑竹mydeman實(shí)際實(shí)驗(yàn)后指出,E680I的確可以實(shí)現(xiàn)真全屏,可能是各個(gè)版本不同的關(guān)系請(qǐng)廣大站友自己實(shí)驗(yàn)后得出正確結(jié)論,然后反饋給我)
          原帖地址:http://www.j2medev.com/bbs/dispbbs.asp?boardID=19&ID=6216&page=1

          13.J2ME中顯示時(shí)間的問(wèn)題

          答:Calendar?ca?=?Calendar.getInstance();
          ????????int?year?=ca.get(Calendar.YEAR);
          ????????int?month=ca.get(Calendar.MONTH)+1;
          ????????int?day=ca.get(Calendar.DATE);

          14.這是個(gè)什么錯(cuò)誤MontyThread?-6

          答:程序用了platformRequest來(lái)調(diào)用真機(jī)上不支持的功能
          原帖地址:http://www.j2medev.com/bbs/dispbbs.asp?boardID=2&ID=6334&page=1

          15.JDK1.5可否用來(lái)開(kāi)發(fā)MIDP,

          答:可以

          16.如何由jar生成相應(yīng)的jad文件

          答:用ezJad等生成工具。
          原帖地址:http://www.j2medev.com/bbs/dispbbs.asp?boardID=17&ID=6019&page=3
          工具下載地址:http://www.j2medev.com/Soft/ShowSoft.asp?SoftID=299

          17.怎樣判斷g.darwImage()方法是否執(zhí)行完畢一次

          答:加個(gè)flag?或者等paint()執(zhí)行完??
          原帖地址:http://www.j2medev.com/bbs/dispbbs.asp?boardID=2&ID=4683&page=4

          18.eclipse開(kāi)發(fā)的J2ME程序中顯示圖片出現(xiàn)異常

          答:eclipse?中?file--->new--->java---->source?folder?記得一定得是source?folder
          原帖地址:http://www.j2medev.com/bbs/dispbbs.asp?boardID=2&ID=568&page=4

          19.Httpconnect?連接超時(shí)問(wèn)題
          答:It?is?not?possible?to?set?the?connection?timeout?in?a?midlet.?The?timeout?behavior?is?fixed?and?is:1.?For?open(),?if?the?connection?cannot?be?made?after?60?seconds,?the?open()?will?throw?IOException.2.?For?read(),?if?no?data?arrives?after?40?seconds,?the?read()?will?throw?IOException.3.?For?write(),?if?the?data?cannot?be?sent?out?after?40?seconds,?the?write()?will?throw?IOException.
          原帖地址:http://www.j2medev.com/bbs/dispbbs.asp?boardID=2&ID=5345&page=5

          20.motov600的左右軟鍵怎么用
          答:v600的左右鍵為21,22和E398的正好相反.
          原帖地址:http://www.j2medev.com/bbs/dispbbs.asp?boardID=2&ID=5284&page=5
          posted @ 2006-04-29 09:11 崛起的程序員 閱讀(230) | 評(píng)論 (0)編輯 收藏
          PHP V5 新的面向?qū)ο缶幊烫匦燥@著提升了這個(gè)流行語(yǔ)言中的功能層次。學(xué)習(xí)如何用 PHP V5 動(dòng)態(tài)特性創(chuàng)建可以滿足需求的對(duì)象。

          PHP V5 中新的面向?qū)ο缶幊蹋∣OP)特性的引入顯著提升了這個(gè)編程語(yǔ)言的功能層次。現(xiàn)在不僅有了私有的、受保護(hù)的和公共的成員變量和函數(shù) —— 就像在 Java?、 C++ 或 C# 編程語(yǔ)言中一樣 —— 但是還可以創(chuàng)建在運(yùn)行時(shí)變化的對(duì)象,即動(dòng)態(tài)地創(chuàng)建新方法和成員變量。而使用 Java、C++ 或 C# 語(yǔ)言是做不到這件事的。這種功能使得超級(jí)快速的應(yīng)用程序開(kāi)發(fā)系統(tǒng)(例如 Ruby on Rails)成為可能。

          但是,在進(jìn)入這些之前,有一點(diǎn)要注意:本文介紹 PHP V5 中非常高級(jí)的 OOP 特性的使用,但是這類特性不是在每個(gè)應(yīng)用程序中都需要的。而且,如果不具備 OOP 的堅(jiān)實(shí)基礎(chǔ)以及 PHP 對(duì)象語(yǔ)法的初步知識(shí),這類特性將會(huì)很難理解。

          動(dòng)態(tài)的重要性

          對(duì)象是把雙刃劍。一方面,對(duì)象是封裝數(shù)據(jù)和邏輯并創(chuàng)建更容易維護(hù)的系統(tǒng)的重大方式。但另一方面,它們會(huì)變得很繁瑣,需要許多冗余的代碼,這時(shí)可能最希望做到的就是不要犯錯(cuò)。這類問(wèn)題的一個(gè)示例來(lái)自數(shù)據(jù)庫(kù)訪問(wèn)對(duì)象。一般來(lái)說(shuō),想用一個(gè)類代表每個(gè)數(shù)據(jù)庫(kù)表,并執(zhí)行以下功能:對(duì)象從數(shù)據(jù)庫(kù)讀出數(shù)據(jù)行;允許更新字段,然后用新數(shù)據(jù)更新數(shù)據(jù)庫(kù)或刪除行。還有一種方法可以創(chuàng)建新的空對(duì)象,設(shè)置對(duì)象的字段,并把數(shù)據(jù)插入數(shù)據(jù)庫(kù)。

          如果在數(shù)據(jù)庫(kù)中有一個(gè)表,名為 Customers,那么就應(yīng)當(dāng)有一個(gè)對(duì)象,名為 Customer,它應(yīng)當(dāng)擁有來(lái)自表的字段,并代表一個(gè)客戶。而且 Customer 對(duì)象應(yīng)當(dāng)允許插入、更新或刪除數(shù)據(jù)庫(kù)中對(duì)應(yīng)的記錄。現(xiàn)在,一切都很好,而且有也很多意義。但是,有許多代碼要編寫(xiě)。如果在數(shù)據(jù)庫(kù)中有 20 個(gè)表,就需要 20 個(gè)類。

          有三個(gè)解決方案可以采用。第一個(gè)解決方案就是,坐在鍵盤(pán)前,老老實(shí)實(shí)地錄入一段時(shí)間。對(duì)于小項(xiàng)目來(lái)說(shuō),這還可以,但是我很懶。第二個(gè)解決方案是用代碼生成器,讀取數(shù)據(jù)庫(kù)模式,并自動(dòng)編寫(xiě)代碼。這是個(gè)好主意,而且是另一篇文章的主題。第三個(gè)解決方案,也是我在本文中介紹的,是編寫(xiě)一個(gè)類,在運(yùn)行時(shí)動(dòng)態(tài)地把自己塑造成指定表的字段。這個(gè)類執(zhí)行起來(lái)比起特定于表的類可能有點(diǎn)慢 —— 但是把我從編寫(xiě)大量代碼中解脫出來(lái)。這個(gè)解決方案在項(xiàng)目開(kāi)始的時(shí)候特別有用,因?yàn)檫@時(shí)表和字段不斷地變化,所以跟上迅速的變化是至關(guān)重要的。

          所以,如何才能編寫(xiě)一個(gè)能夠彎曲 的類呢?





          回頁(yè)首


          寫(xiě)一個(gè)柔性的類

          對(duì)象有兩個(gè)方面:成員變量方法。在編譯語(yǔ)言(例如 Java)中,如果想調(diào)用不存在的方法或引用不存在的成員變量,會(huì)得到編譯時(shí)錯(cuò)誤。但是,在非編譯語(yǔ)言,例如 PHP 中,會(huì)發(fā)生什么?

          在 PHP 中的方法調(diào)用是這樣工作的。首先,PHP 解釋器在類上查找方法。如果方法存在,PHP 就調(diào)用它。如果沒(méi)有,那么就調(diào)用類上的魔法方法 __call(如果這個(gè)方法存在的話)。如果 __call 失敗,就調(diào)用父類方法,依此類推。

          魔法方法
          魔法方法是有特定名稱的方法,PHP 解釋器在腳本執(zhí)行的特定點(diǎn)上會(huì)查找魔法方法。最常見(jiàn)的魔法方法就是對(duì)象創(chuàng)始時(shí)調(diào)用的構(gòu)造函數(shù)。

          __call 方法有兩個(gè)參數(shù):被請(qǐng)求的方法的名稱和方法參數(shù)。如果創(chuàng)建的 __call 方法接受這兩個(gè)參數(shù),執(zhí)行某項(xiàng)功能,然后返回 TRUE,那么調(diào)用這個(gè)對(duì)象的代碼就永遠(yuǎn)不會(huì)知道在有代碼的方法和 __call 機(jī)制處理的方法之間的區(qū)別。通過(guò)這種方式,可以創(chuàng)建這樣的對(duì)象,即動(dòng)態(tài)地模擬擁有無(wú)數(shù)方法的情況。

          除了 __call 方法,其他魔法方法 —— 包括 __get__set —— 調(diào)用它們的時(shí)候,都是因?yàn)橐昧瞬淮嬖诘膶?shí)例變量。腦子里有了這個(gè)概念之后,就可以開(kāi)始編寫(xiě)能夠適應(yīng)任何表的動(dòng)態(tài)數(shù)據(jù)庫(kù)訪問(wèn)類了。





          回頁(yè)首


          經(jīng)典的數(shù)據(jù)庫(kù)訪問(wèn)

          先從一個(gè)簡(jiǎn)單的數(shù)據(jù)庫(kù)模式開(kāi)始。清單 1 所示的模式針對(duì)的是單一的數(shù)據(jù)表數(shù)據(jù)庫(kù),容納圖書(shū)列表。


          清單 1. MySQL 數(shù)據(jù)庫(kù)模式
          														
          																DROP TABLE IF EXISTS book;
          CREATE TABLE book (
                  book_id INT NOT NULL AUTO_INCREMENT,
                  title TEXT,
                  publisher TEXT,
                  author TEXT,
                  PRIMARY KEY( book_id )
          );
          
          														
          												

          請(qǐng)把這個(gè)模式裝入到名為 bookdb 的數(shù)據(jù)庫(kù)。

          接下來(lái),編寫(xiě)一個(gè)常規(guī)的數(shù)據(jù)庫(kù)類,然后再把它修改成動(dòng)態(tài)的。清單 2 顯示了圖書(shū)表的簡(jiǎn)單的數(shù)據(jù)庫(kù)訪問(wèn)類。


          清單 2. 基本的數(shù)據(jù)庫(kù)訪問(wèn)客戶機(jī)
          														
          																<?php
          require_once("DB.php");
          
          $dsn = 'mysql://root:password@localhost/bookdb';
          $db =& DB::Connect( $dsn, array() );
          if (PEAR::isError($db)) { die($db->getMessage()); }
          
          class Book
          {
            private $book_id;
            private $title;
            private $author;
            private $publisher;
          
            function __construct()
            {
            }
          
            function set_title( $title ) { $this->title = $title; }
            function get_title( ) { return $this->title; }
          
            function set_author( $author ) { $this->author = $author; }
            function get_author( ) { return $this->author; }
          
            function set_publisher( $publisher ) {
            $this->publisher = $publisher; }
            function get_publisher( ) { return $this->publisher; }
          
            function load( $id )
            {
              global $db;
          $res = $db->query( "SELECT * FROM book WHERE book_id=?",
              array( $id ) );
              $res->fetchInto( $row, DB_FETCHMODE_ASSOC );
              $this->book_id = $id;
              $this->title = $row['title'];
              $this->author = $row['author'];
              $this->publisher = $row['publisher'];
            }
          
            function insert()
            {
              global $db;
              $sth = $db->prepare(
          'INSERT INTO book ( book_id, title, author, publisher )
              VALUES ( 0, ?, ?, ? )'
              );
              $db->execute( $sth,
                array( $this->title,
                  $this->author,
                  $this->publisher ) );
              $res = $db->query( "SELECT last_insert_id()" );
              $res->fetchInto( $row );
              return $row[0];
            }
          
            function update()
            {
              global $db;
              $sth = $db->prepare(
          'UPDATE book SET title=?, author=?, publisher=?
             WHERE book_id=?'
              );
              $db->execute( $sth,
                array( $this->title,
                  $this->author,
                  $this->publisher,
                  $this->book_id ) );
            }
          
            function delete()
            {
              global $db;
              $sth = $db->prepare(
                'DELETE FROM book WHERE book_id=?'
              );
              $db->execute( $sth,
                array( $this->book_id ) );
            }
          
            function delete_all()
            {
              global $db;
              $sth = $db->prepare( 'DELETE FROM book' );
              $db->execute( $sth );
            }
          }
          
          $book = new Book();
          $book->delete_all();
          $book->set_title( "PHP Hacks" );
          $book->set_author( "Jack Herrington" );
          $book->set_publisher( "O'Reilly" );
          $id = $book->insert();
          echo ( "New book id = $id\n" );
          
          $book2 = new Book();
          $book2->load( $id );
          echo( "Title = ".$book2->get_title()."\n" );
          $book2->delete( );
          ?>
          
          														
          												

          為了保持代碼簡(jiǎn)單,我把類和測(cè)試代碼放在一個(gè)文件中。文件首先得到數(shù)據(jù)庫(kù)句柄,句柄保存在一個(gè)全局變量中。然后定義 Book 類,用私有成員變量代表每個(gè)字段。還包含了一套用來(lái)從數(shù)據(jù)庫(kù)裝入、插入、更新和刪除行的方法。

          底部的測(cè)試代碼先刪除數(shù)據(jù)庫(kù)中的所有條目。然后,代碼插入一本書(shū),輸出新記錄的 ID。然后,代碼把這本書(shū)裝入另一個(gè)對(duì)象并輸出書(shū)名。

          清單 3 顯示了在命令行上用 PHP 解釋器運(yùn)行代碼的效果。


          清單 3. 在命令行運(yùn)行代碼
          														
          																% php db1.php
          New book id = 25
          Title = PHP Hacks
          %
          
          														
          												

          不需要看太多,就已經(jīng)得到重點(diǎn)了。Book 對(duì)象代表圖書(shū)數(shù)據(jù)表中的行。通過(guò)使用上面的字段和方法,可以創(chuàng)建新行、更新行和刪除行。





          回頁(yè)首


          初識(shí)動(dòng)態(tài)

          下一步是讓類變得稍微動(dòng)態(tài)一些:動(dòng)態(tài)地為每個(gè)字段創(chuàng)建 get_set_ 方法。清單 4 顯示了更新后的代碼。


          清單 4. 動(dòng)態(tài) get_ 和 set_ 方法
          														
          																<?php
          require_once("DB.php");
          
          $dsn = 'mysql://root:password@localhost/bookdb';
          $db =& DB::Connect( $dsn, array() );
          if (PEAR::isError($db)) { die($db->getMessage()); }
          
          class Book
          {
            private $book_id;
            private $fields = array();
          
            function __construct()
            {
              $this->fields[ 'title' ] = null;
              $this->fields[ 'author' ] = null;
              $this->fields[ 'publisher' ] = null;
            }
          
            function __call( $method, $args )
            {
              if ( preg_match( "/set_(.*)/", $method, $found ) )
              {
                if ( array_key_exists( $found[1], $this->fields ) )
                {
                  $this->fields[ $found[1] ] = $args[0];
                  return true;
                }
              }
              else if ( preg_match( "/get_(.*)/", $method, $found ) )
              {
                if ( array_key_exists( $found[1], $this->fields ) )
                {
                  return $this->fields[ $found[1] ];
                }
              }
              return false;
            }
          
            function load( $id )
            {
              global $db;
          $res = $db->query( "SELECT * FROM book WHERE book_id=?",
             array( $id ) );
              $res->fetchInto( $row, DB_FETCHMODE_ASSOC );
              $this->book_id = $id;
              $this->set_title( $row['title'] );
              $this->set_author( $row['author'] );
              $this->set_publisher( $row['publisher'] );
            }
          
            function insert()
            {
              global $db;
              $sth = $db->prepare(
          'INSERT INTO book ( book_id, title, author, publisher )
             VALUES ( 0, ?, ?, ? )'
              );
              $db->execute( $sth,
                array( $this->get_title(),
                  $this->get_author(),
                  $this->get_publisher() ) );
              $res = $db->query( "SELECT last_insert_id()" );
              $res->fetchInto( $row );
              return $row[0];
            }
          
            function update()
            {
              global $db;
              $sth = $db->prepare(
          'UPDATE book SET title=?, author=?, publisher=?
            WHERE book_id=?'
              );
              $db->execute( $sth,
                array( $this->get_title(),
                  $this->get_author(),
                  $this->get_publisher(),
                  $this->book_id ) );
            }
          
            function delete()
            {
              global $db;
              $sth = $db->prepare(
                'DELETE FROM book WHERE book_id=?'
              );
              $db->execute( $sth,
                array( $this->book_id ) );
            }
          
            function delete_all()
            {
              global $db;
              $sth = $db->prepare( 'DELETE FROM book' );
              $db->execute( $sth );
            }
          }
          
          ..
          
          														
          												

          要做這個(gè)變化,需要做兩件事。首先,必須把字段從單個(gè)實(shí)例變量修改成字段和值組合構(gòu)成的散列表。然后必須添加一個(gè) __call 方法,它只查看方法名稱,看方法是 set_ 還是 get_ 方法,然后在散列表中設(shè)置適當(dāng)?shù)淖侄巍?/font>

          注意,load 方法通過(guò)調(diào)用 set_titleset_authorset_publisher方法 —— 實(shí)際上都不存在 —— 來(lái)實(shí)際使用 __call 方法。





          回頁(yè)首


          走向完全動(dòng)態(tài)

          刪除 get_set_ 方法只是一個(gè)起點(diǎn)。要?jiǎng)?chuàng)建完全動(dòng)態(tài)的數(shù)據(jù)庫(kù)對(duì)象,必須向類提供表和字段的名稱,還不能有硬編碼的引用。清單 5 顯示了這個(gè)變化。


          清單 5. 完全動(dòng)態(tài)的數(shù)據(jù)庫(kù)對(duì)象類
          														
          																<?php
          require_once("DB.php");
          
          $dsn = 'mysql://root:password@localhost/bookdb';
          $db =& DB::Connect( $dsn, array() );
          if (PEAR::isError($db)) { die($db->getMessage()); }
          
          class DBObject
          {
            private $id = 0;
            private $table;
            private $fields = array();
          
            function __construct( $table, $fields )
            {
              $this->table = $table;
              foreach( $fields as $key )
                $this->fields[ $key ] = null;
            }
          
            function __call( $method, $args )
            {
              if ( preg_match( "/set_(.*)/", $method, $found ) )
              {
                if ( array_key_exists( $found[1], $this->fields ) )
                {
                  $this->fields[ $found[1] ] = $args[0];
                  return true;
                }
              }
              else if ( preg_match( "/get_(.*)/", $method, $found ) )
              {
                if ( array_key_exists( $found[1], $this->fields ) )
                {
                  return $this->fields[ $found[1] ];
                }
              }
              return false;
            }
          
            function load( $id )
            {
              global $db;
              $res = $db->query(
            "SELECT * FROM ".$this->table." WHERE ".
            $this->table."_id=?",
                array( $id )
              );
              $res->fetchInto( $row, DB_FETCHMODE_ASSOC );
              $this->id = $id;
              foreach( array_keys( $row ) as $key )
                $this->fields[ $key ] = $row[ $key ];
            }
          
            function insert()
            {
              global $db;
          
              $fields = $this->table."_id, ";
              $fields .= join( ", ", array_keys( $this->fields ) );
          
              $inspoints = array( "0" );
              foreach( array_keys( $this->fields ) as $field )
                $inspoints []= "?";
              $inspt = join( ", ", $inspoints );
          
          $sql = "INSERT INTO ".$this->table." ( $fields )
             VALUES ( $inspt )";
          
              $values = array();
              foreach( array_keys( $this->fields ) as $field )
                $values []= $this->fields[ $field ];
          
              $sth = $db->prepare( $sql );
              $db->execute( $sth, $values );
          
              $res = $db->query( "SELECT last_insert_id()" );
              $res->fetchInto( $row );
              $this->id = $row[0];
              return $row[0];
            }
          
            function update()
            {
              global $db;
          
              $sets = array();
              $values = array();
              foreach( array_keys( $this->fields ) as $field )
              {
                $sets []= $field.'=?';
                $values []= $this->fields[ $field ];
              }
              $set = join( ", ", $sets );
              $values []= $this->id;
          
          $sql = 'UPDATE '.$this->table.' SET '.$set.
            ' WHERE '.$this->table.'_id=?';
          
              $sth = $db->prepare( $sql );
              $db->execute( $sth, $values );
            }
          
            function delete()
            {
              global $db;
              $sth = $db->prepare(
             'DELETE FROM '.$this->table.' WHERE '.
             $this->table.'_id=?'
              );
              $db->execute( $sth,
                array( $this->id ) );
            }
          
            function delete_all()
            {
              global $db;
              $sth = $db->prepare( 'DELETE FROM '.$this->table );
              $db->execute( $sth );
            }
          }
          
          $book = new DBObject( 'book', array( 'author',
             'title', 'publisher' ) );
          $book->delete_all();
          $book->set_title( "PHP Hacks" );
          $book->set_author( "Jack Herrington" );
          $book->set_publisher( "O'Reilly" );
          $id = $book->insert();
          
          echo ( "New book id = $id\n" );
          
          $book->set_title( "Podcasting Hacks" );
          $book->update();
          
          $book2 = new DBObject( 'book', array( 'author',
            'title', 'publisher' ) );
          $book2->load( $id );
          echo( "Title = ".$book2->get_title()."\n" );
          $book2->delete( );
          ? >
          
          														
          												

          在這里,把類的名稱從 Book 改成 DBObject。然后,把構(gòu)造函數(shù)修改成接受表的名稱和表中字段的名稱。之后,大多數(shù)變化發(fā)生在類的方法中,過(guò)去使用一些硬編碼結(jié)構(gòu)化查詢語(yǔ)言(SQL),現(xiàn)在則必須用表和字段的名稱動(dòng)態(tài)地創(chuàng)建 SQL 字符串。

          代碼的惟一假設(shè)就是只有一個(gè)主鍵字段,而且這個(gè)字段的名稱是表名加上 _id。所以,在 book 表這個(gè)示例中,有一個(gè)主鍵字段叫做 book_id。主鍵的命名標(biāo)準(zhǔn)可能不同;如果這樣,需要修改代碼以符合標(biāo)準(zhǔn)。

          這個(gè)類比最初的 Book 類復(fù)雜得多。但是,從類的客戶的角度來(lái)看,這個(gè)類用起來(lái)仍很簡(jiǎn)單。也就是說(shuō),我認(rèn)為這個(gè)類能更簡(jiǎn)單。具體來(lái)說(shuō),我不愿意每次創(chuàng)建圖書(shū)的時(shí)候都要指定表和字段的名稱。如果我四處拷貝和粘貼這個(gè)代碼,然后修改了 book 表的字段結(jié)構(gòu),那么我可能就麻煩了。在清單 6 中,通過(guò)創(chuàng)建一個(gè)繼承自 DBObject 的簡(jiǎn)單 Book 類,我解決了這個(gè)問(wèn)題。


          清單 6. 新的 Book 類
          														
          																..
          class Book extends DBObject 
          {
            function __construct()
            {
              parent::__construct( 'book', 
                array( 'author', 'title', 'publisher' ) );
            }
          }
          
          $book = new Book( );
          $book->delete_all();
          $book->{'title'} = "PHP Hacks";
          $book->{'author'} = "Jack Herrington";
          $book->{'publisher'} = "O'Reilly";
          $id = $book->insert();
          
          echo ( "New book id = $id\n" );
          
          $book->{'title'} = "Podcasting Hacks";
          $book->update();
          
          $book2 = new Book( );
          $book2->load( $id );
          echo( "Title = ".$book2->{'title'}."\n" );
          $book2->delete( );
          ?>
          
          														
          												

          現(xiàn)在,Book 類真的是簡(jiǎn)單了。而且 Book 類的客戶也不再需要知道表或字段的名稱了。





          回頁(yè)首


          改進(jìn)的空間

          對(duì)這個(gè)動(dòng)態(tài)類我想做的最后一個(gè)改進(jìn),是用成員變量訪問(wèn)字段,而不是用笨重的 get_set_ 操作符。清單 7 顯示了如何用 __get__set 魔法方法代替 __call


          清單 7. 使用 __get 和 __set 方法
          														
          																<?php
          require_once("DB.php");
          
          $dsn = 'mysql://root:password@localhost/bookdb';
          $db =& DB::Connect( $dsn, array() );
          if (PEAR::isError($db)) { die($db->getMessage()); }
          
          class DBObject
          {
            private $id = 0;
            private $table;
            private $fields = array();
          
            function __construct( $table, $fields )
            {
              $this->table = $table;
              foreach( $fields as $key )
                $this->fields[ $key ] = null;
            }
          
            function __get( $key )
            {
              return $this->fields[ $key ];
            }
          
            function __set( $key, $value )
            {
              if ( array_key_exists( $key, $this->fields ) )
              {
                $this->fields[ $key ] = $value;
                return true;
              }
              return false;
            }
          
            function load( $id )
            {
              global $db;
              $res = $db->query(
            "SELECT * FROM ".$this->table." WHERE ".
             $this->table."_id=?",
                array( $id )
              );
              $res->fetchInto( $row, DB_FETCHMODE_ASSOC );
              $this->id = $id;
              foreach( array_keys( $row ) as $key )
                $this->fields[ $key ] = $row[ $key ];
            }
          
            function insert()
            {
              global $db;
          
              $fields = $this->table."_id, ";
              $fields .= join( ", ", array_keys( $this->fields ) );
          
              $inspoints = array( "0" );
              foreach( array_keys( $this->fields ) as $field )
                $inspoints []= "?";
              $inspt = join( ", ", $inspoints );
          
          $sql = "INSERT INTO ".$this->table. 
             " ( $fields ) VALUES ( $inspt )";
          
              $values = array();
              foreach( array_keys( $this->fields ) as $field )
                $values []= $this->fields[ $field ];
          
              $sth = $db->prepare( $sql );
              $db->execute( $sth, $values );
          
              $res = $db->query( "SELECT last_insert_id()" );
              $res->fetchInto( $row );
              $this->id = $row[0];
              return $row[0];
            }
          
            function update()
            {
              global $db;
          
              $sets = array();
              $values = array();
              foreach( array_keys( $this->fields ) as $field )
              {
                $sets []= $field.'=?';
                $values []= $this->fields[ $field ];
              }
              $set = join( ", ", $sets );
              $values []= $this->id;
          
          $sql = 'UPDATE '.$this->table.' SET '.$set.
            ' WHERE '.$this->table.'_id=?';
          
              $sth = $db->prepare( $sql );
              $db->execute( $sth, $values );
            }
          
            function delete()
            {
              global $db;
              $sth = $db->prepare(
          'DELETE FROM '.$this->table.' WHERE '.
          $this->table.'_id=?'
              );
              $db->execute( $sth,
                array( $this->id ) );
            }
          
            function delete_all()
            {
              global $db;
              $sth = $db->prepare( 'DELETE FROM '.$this->table );
              $db->execute( $sth );
            }
          }
          
          class Book extends DBObject 
          {
            function __construct()
            {
            parent::__construct( 'book',
              array( 'author', 'title', 'publisher' ) );
            }
          }
          
          $book = new Book( );
          $book->delete_all();
          $book->{'title'} = "PHP Hacks";
          $book->{'author'} = "Jack Herrington";
          $book->{'publisher'} = "O'Reilly";
          $id = $book->insert();
          
          echo ( "New book id = $id\n" );
          
          $book->{'title'} = "Podcasting Hacks";
          $book->update();
          
          $book2 = new Book( );
          $book2->load( $id );
          echo( "Title = ".$book2->{'title'}."\n" );
          $book2->delete( );
          ?>
          
          														
          												

          底部的測(cè)試代碼只演示了這個(gè)語(yǔ)法干凈了多少。要得到圖書(shū)的書(shū)名,只需得到 title 成員變量。這個(gè)變量會(huì)調(diào)用對(duì)象的 __get 方法,在散列表中查找 title 條目并返回。

          現(xiàn)在就得到了單個(gè)動(dòng)態(tài)的數(shù)據(jù)庫(kù)訪問(wèn)類,它能夠讓自己適應(yīng)到數(shù)據(jù)庫(kù)中的任何表。





          回頁(yè)首


          動(dòng)態(tài)類的更多用途

          編寫(xiě)動(dòng)態(tài)類不僅限于數(shù)據(jù)庫(kù)訪問(wèn)。請(qǐng)看清單 8 中的 Customer 對(duì)象這個(gè)例子。


          清單 8. 簡(jiǎn)單的 Customer 對(duì)象
          														
          																<?php
          class Customer
          {
            private $name;
          
            function set_name( $value )
            {
              $this->name = $value;
            }
          
            function get_name()
            {
              return $this->name;
            }
          }
          
          $c1 = new Customer();
          $c1->set_name( "Jack" );
          $name = $c1->get_name();
          echo( "name = $name\n" );
          ?>
          
          														
          												

          這個(gè)對(duì)象足夠簡(jiǎn)單。但是如果我想在每次檢索或設(shè)置客戶名稱時(shí)都記錄日志,會(huì)發(fā)生什么呢?我可以把這個(gè)對(duì)象包裝在一個(gè)動(dòng)態(tài)日志對(duì)象內(nèi),這個(gè)對(duì)象看起來(lái)像 Customer 對(duì)象,但是會(huì)把 getset 操作的通知發(fā)送給日志。清單 9 顯示了這類包裝器對(duì)象。


          清單 9. 動(dòng)態(tài)包裝器對(duì)象
          														
          																<?php
          class Customer
          {
            private $name;
          
            function set_name( $value )
            {
              $this->name = $value;
            }
          
            function get_name()
            {
              return $this->name;
            }
          }
          
          class Logged
          {
            private $obj;
          
            function __call( $method, $args )
            {
              echo( "$method( ".join( ",", $args )." )\n" );
          return call_user_func_array(array(&$this->obj,
             $method), $args );
            }
          
            function __construct( $obj )
            {
              $this->obj = $obj;
            }
          }
          
          $c1 = new Logged( new Customer() );
          $c1->set_name( "Jack" );
          $name = $c1->get_name();
          echo( "name = $name\n" );
          ?>
          
          														
          												

          調(diào)用日志版本的 Customer 的代碼看起來(lái)與前面相同,但是這時(shí),對(duì) Customer 對(duì)象的任何訪問(wèn)都被記入日志。清單 10 顯示了運(yùn)行這個(gè)日志版代碼時(shí)輸出的日志。


          清單 10. 運(yùn)行日志版對(duì)象
          														
          																% php log2.php
          set_name( Jack )
          get_name(  )
          name = Jack
          %
          
          														
          												

          在這里,日志輸出表明用參數(shù) Jack 調(diào)用了set_name 方法。然后,調(diào)用 get_name 方法。最后,測(cè)試代碼輸出 get_name 調(diào)用的結(jié)果。





          回頁(yè)首


          結(jié)束語(yǔ)

          如果這個(gè)動(dòng)態(tài)對(duì)象素材對(duì)您來(lái)說(shuō)理解起來(lái)有點(diǎn)難,我不會(huì)責(zé)備您。因?yàn)槲易约阂不瞬簧贂r(shí)間研究它并使用代碼才理解它并看出它的好處。

          動(dòng)態(tài)對(duì)象有許多功能,但是也有相當(dāng)?shù)娘L(fēng)險(xiǎn)。首先,在剛開(kāi)始編寫(xiě)魔法方法時(shí),類的復(fù)雜性顯著增加。這些類更難理解、調(diào)試和維護(hù)。另外,因?yàn)榧砷_(kāi)發(fā)環(huán)境(IDE)變得越來(lái)越智能,所以在處理動(dòng)態(tài)類時(shí)它們也會(huì)遇到這類問(wèn)題,因?yàn)楫?dāng)它們?cè)陬惿喜檎曳椒〞r(shí)會(huì)找不到方法。

          現(xiàn)在,并不是說(shuō)應(yīng)當(dāng)避免編寫(xiě)這類代碼。相反。我非常喜歡 PHP 的設(shè)計(jì)者這么有想法,把這些魔法方法包含在語(yǔ)言中,這樣我們才能編寫(xiě)這類代碼。但是重要的是,既要理解優(yōu)點(diǎn),也要理解不足。

          當(dāng)然,對(duì)于應(yīng)用程序(例如數(shù)據(jù)庫(kù)訪問(wèn))來(lái)說(shuō),在這里介紹的技術(shù) —— 與廣泛流行的 Ruby on Rails 系統(tǒng)上使用的技術(shù)類似 —— 能夠極大地減少用 PHP 實(shí)現(xiàn)數(shù)據(jù)庫(kù)應(yīng)用程序所需要的時(shí)間。節(jié)約時(shí)間總不是壞事。





          回頁(yè)首


          參考資料

          學(xué)習(xí)
          posted @ 2006-04-28 16:02 崛起的程序員 閱讀(209) | 評(píng)論 (0)編輯 收藏

          年輕人買(mǎi)套套的經(jīng)歷

            顧客“老板套子怎么賣(mài)?”

            老板“10元一個(gè)”

            顧客“我先試試行么?”

            老板“還試什么呀?便宜點(diǎn)9元好了。”

            顧客“暈,這也叫便宜啊?”

            老板“好啦8元可以了吧。”

            顧客“......”

            老板“不會(huì)還嫌貴吧?”

            顧客“不是貴,是讓我精盡人亡啊”

            老板“沒(méi)那么夸張吧,看你是小朋友,7元好了”

            顧客“恩,差不多啦,可是我沒(méi)那么多錢(qián)啊。”

            老板“啊?你有多少啊?”

            顧客“5元。”

            老板“天啊,暈死了,怎么也得再添1元啊!”

            顧客“我很想添,可是我的資金有限啊”

            老板“好啦,我認(rèn)倒霉,5元成交”

            顧客“我不是要給你5元,我得留下2元做車(chē)”

            老板“不會(huì)吧,你不會(huì)做車(chē)來(lái)這里買(mǎi)這東西吧?”

            顧客“是啊我做11路來(lái)的而且還是回頭客啊”

            老板“雖然以前沒(méi)看過(guò)你,不過(guò)希望你以后再來(lái),3元成交行了吧。”

            顧客(臉上帶紅)“可是我還沒(méi)有對(duì)象”

            老板“啊?那你買(mǎi)這干什么啊?”

            顧客“沒(méi)關(guān)系,如果你再便宜1元的話我就能找到了!”

            老板“¥%……¥%……%¥算你狠,2元行了吧!”

            顧客“等等,這個(gè)怎么有個(gè)洞啊?”

            老板“沒(méi)有洞怎么用啊!?”

            顧客“怎么看起來(lái)像用過(guò)的啊?”

            老板“侮辱我可以但是不要侮辱我的套子,這絕對(duì)是新的。”

            顧客“哇,上面還沒(méi)干呢啊,你騙我啊!”

            老板“啊!!不好意思嘿嘿……做生意嗎,你要知道我每天的門(mén)面房租金上千呢,不然我吃什么,1元可以了吧”

            顧客“你這種行為嚴(yán)重的危害了我的健康并且深深的影響了我的心靈.......”

            老板“啊呀!這么嚴(yán)重啊,你別生氣,我5毛賣(mài)給你行了吧。”

            顧客“好,開(kāi)張發(fā)票來(lái)!”

            老板暈死!

          十二個(gè)避孕套

            爸爸和13歲的兒子走進(jìn)屈臣氏,路經(jīng)放避孕套的貨架。兒子問(wèn)爸爸「這些一盒盒的是什

          么?爸爸告訴兒子:「這些是避孕套,是用來(lái)進(jìn)行安全的性行為用的。兒子U「啊~原來(lái)這些

          便是避孕套,上性教育課老師曾提及過(guò)!........[但為什么這些要一盒入里面有三個(gè)的?

            爸爸:「嗯......這些是給大學(xué)生用的,星期五一個(gè),星期六一個(gè),星期日一........」

            兒子:「.......那么這些一盒六個(gè)的是誰(shuí)用的?」

            爸爸:「嗯........這是研究生用的,星期五兩個(gè),星期六兩個(gè),星期日兩個(gè)........」

            兒子:「.......那這些呢?」

            兒子拿起了一盒十二個(gè)裝的。

            爸爸透了一下涼氣,凄凄道:「那是給已婚人仕用的,一月份一個(gè),二月份一個(gè),三月份一個(gè)............」


          彩色的保險(xiǎn)套

            有一個(gè)人想嘗試新奇的事,便跑到情趣商品店買(mǎi)彩色的保險(xiǎn)套他看到兩個(gè)彩色的套子,

          一個(gè)是黑色的,一個(gè)外型像是米老鼠他決定買(mǎi)那個(gè)黑色的回家,并跟太太大戰(zhàn)了幾回合不過(guò)

          那個(gè)套子并沒(méi)發(fā)生什作用,后來(lái)他太太懷孕了經(jīng)過(guò)九月之后生下小baby,再經(jīng)過(guò)6年之后孩子

          長(zhǎng)大了這個(gè)小孩有一天問(wèn)他老爸:“為什么哥哥姊姊的膚色都是白的而我卻是黑的?”爸爸

          回答道:“孩子,你沒(méi)長(zhǎng)得像米老鼠就該謝天謝地了”


          IT避孕套

          有一天軟件工業(yè)一蹶不振,軟件業(yè)三大巨頭SUN,UNIX和微軟都決定改做避孕套生意,

          他們生產(chǎn)的避孕套分別命名為JAVA避孕套,X避孕套和MS避孕套。 一個(gè)使用JAVA避孕

          套的顧客來(lái)到SUN公司投訴,說(shuō)戴著不合適,SUN公司回答說(shuō)要等國(guó)際標(biāo)準(zhǔn)組織(ISO)制定相

          應(yīng)的標(biāo)準(zhǔn)才行,并吹牛說(shuō)那時(shí)他們生產(chǎn)的避孕套將適合每個(gè)男人,顧客只好轉(zhuǎn)而使用X避孕

          套。可他發(fā)現(xiàn)等他讀完隨套附上的說(shuō)明書(shū)后,他的妻子已經(jīng)睡著了,他自己也忘了為什么

          要用X避孕套。最后,他只好換用MS避孕套。出乎他意料的是,MS避孕套非常好用,他很愉

          快的連續(xù)使用了好幾個(gè)月,突然發(fā)現(xiàn)他妻子懷孕了。他非常生氣氣勢(shì)洶洶的找到微軟公

          司,微軟的回答是:補(bǔ)丁馬上就到!

          posted @ 2006-04-28 13:46 崛起的程序員 閱讀(560) | 評(píng)論 (1)編輯 收藏
          Stripes 1.3 版本發(fā)布了.Stripes是一個(gè)視圖框架用于利用最新的Java技術(shù)來(lái)構(gòu)建Web應(yīng)用程序.
          文章來(lái)源:http://www.matrix.org.cn/resource/news/670_Stripes.html
          posted @ 2006-04-28 11:29 崛起的程序員 閱讀(218) | 評(píng)論 (0)編輯 收藏
          JIRA 3.6 版本發(fā)布了.JIRA是一個(gè)優(yōu)秀的問(wèn)題(or bugs,task,improvement,new feature )跟蹤及管理軟件。
          文章來(lái)源:http://www.matrix.org.cn/resource/news/671_JIRA.html
          posted @ 2006-04-28 11:29 崛起的程序員 閱讀(215) | 評(píng)論 (0)編輯 收藏
          Apache MyFaces 1.1.2 版本發(fā)布了.MyFaces是JavaServer Faces(JSF) Web框架 (JSR 127)的一個(gè)實(shí)現(xiàn)。JavaServer Faces Web框架是一個(gè)新的實(shí)現(xiàn)MVC模式的規(guī)范.它可以與Struts框架相媲美甚至的一些特性與觀念已經(jīng)超過(guò)了Struts.
          文章來(lái)源:http://www.matrix.org.cn/resource/news/672_Apache+MyFaces.html
          posted @ 2006-04-28 11:29 崛起的程序員 閱讀(226) | 評(píng)論 (0)編輯 收藏
          Apple 發(fā)布了 Mac OS X Tiger 的更新包.for for Mac OS X 10.4.5 Tiger 用戶.更新包增加了對(duì)Java 2 Platform Standard Edition 5.0的可靠性和兼容性.
          文章來(lái)源:http://www.matrix.org.cn/resource/news/673_Apple+Tiger+Java.html
          posted @ 2006-04-28 11:29 崛起的程序員 閱讀(253) | 評(píng)論 (0)編輯 收藏
          Apache FOP 0.92 beta 版本發(fā)布了.FOP是Apache計(jì)劃所發(fā)展的一個(gè)開(kāi)源的XSL-FO處理器項(xiàng)目,可以把Formatting Object格式的文件轉(zhuǎn)換成 可列印文件,如PDF、PostScript等格式。
          文章來(lái)源:http://www.matrix.org.cn/resource/news/674_Apache+FOP.html
          posted @ 2006-04-28 11:29 崛起的程序員 閱讀(293) | 評(píng)論 (0)編輯 收藏
          ObjectWeb ASM 3.0 beta2 版本發(fā)布了.ASM是一套JAVA字節(jié)碼生成架構(gòu)。它可以動(dòng)態(tài)生成二進(jìn)制格式的stub類或其他代理類,或者在類被JAVA虛擬機(jī)裝入內(nèi)存之前,動(dòng)態(tài)修改類。
          文章來(lái)源:http://www.matrix.org.cn/resource/news/675_ObjectWeb+ASM.html
          posted @ 2006-04-28 11:29 崛起的程序員 閱讀(268) | 評(píng)論 (0)編輯 收藏
          Apache WS Policy 宣布改名為 Apache Neethi.
          文章來(lái)源:http://www.matrix.org.cn/resource/news/676_Apache+Neethi.html
          posted @ 2006-04-28 11:29 崛起的程序員 閱讀(298) | 評(píng)論 (0)編輯 收藏
          僅列出標(biāo)題
          共9頁(yè): 上一頁(yè) 1 2 3 4 5 6 7 8 9 下一頁(yè) 
          主站蜘蛛池模板: 安庆市| 马龙县| 浪卡子县| 凤城市| 胶南市| 土默特右旗| 祁东县| 佛学| 兴城市| 曲水县| 霞浦县| 元朗区| 岗巴县| 平谷区| 景德镇市| 加查县| 凌源市| 清苑县| 浦东新区| 连城县| 怀柔区| 曲水县| 光山县| 桐庐县| 庐江县| 太保市| 梓潼县| 项城市| 军事| 玉林市| 沛县| 汶上县| 商都县| 南澳县| 公主岭市| 成都市| 阿鲁科尔沁旗| 桃园市| 静安区| 徐州市| 汕头市|