ee ee
歡迎訪問 ==>高老師的博客網(wǎng)頁
高煥堂:MISOO(大數(shù)據(jù).大思考)聯(lián)盟.臺北中心和東京(日本)分社.總教練
EE EE
您好,登錄后才能下訂單哦!
前言:
誰來誕生子類的對象呢? 答案是:框架。這樣讓框架能有絕對的制約能力去「框住」應(yīng)用子類的結(jié)構(gòu)和行為。接著,請你來思考一個有趣的問題:
l框架開發(fā)者(強龍)先寫框架基類的程序碼;
l然后,AP開發(fā)者(地頭蛇)才撰寫應(yīng)用子類在后。
那么框架開發(fā)者事先又如何知道地頭蛇后來撰寫的應(yīng)用子類的名稱呢? 如果不知道應(yīng)用子類的名稱,又如何誕生應(yīng)用子類的對象呢?
ee ee
歡迎訪問 ==>高老師的博客網(wǎng)頁
高煥堂:MISOO(大數(shù)據(jù).大思考)聯(lián)盟.臺北中心和東京(日本)分社.總教練
EE EE
框架如何創(chuàng)建App子類的對象(二)?
--- 由基類創(chuàng)建親生子類的對象
1. 以MediaPlayer播放mp3音樂為例
大家對于拿MediaPlayer來播放mp3音樂的應(yīng)用程序,應(yīng)該不會陌生。最簡單的架構(gòu)如下圖所示:
圖1、由myActivity來創(chuàng)建MediaPlayer的對象
你也可以設(shè)計一個包容器(Wrapper)類別來包裝MediaPlayer類別,也就是由這個Wrapper來幫忙創(chuàng)建MediaPlayer對象,如下圖所示:
圖2、由Wrapper協(xié)助來創(chuàng)建MediaPlayer的對象
無論是在上圖1或圖2的架構(gòu)里,你都是扮演一個傳統(tǒng)的角色:AP開發(fā)者。于此,就來換個新鮮的角色:框架開發(fā)者。在上一篇文章里,已經(jīng)說明了,必須讓框架基類去創(chuàng)建應(yīng)用子類的對象,才能讓框架擁有高度的制約力量。在上一篇文章的范例里(即Ex04_01程序范例)已經(jīng)實踐了這個目標,讓框架基類(如GraphView)來創(chuàng)建子類別(如myDrawing)的對象。其中,值得留意的是:上一篇文章范例里的基類GraphView并不是myDrawing的直系父類別(基類)。簡而言之,myDrawing并不是繼承GraphView基類。亦即,myDrawing并不是GraphView的親生應(yīng)用子類。
于是,在本文里,我們來看看一個基類如何創(chuàng)建親生子類別的對象。如下圖所示:
圖3、由基類Player來創(chuàng)建親生子類mp3Player的對象
大家都知道一個類別本身就是一個對象,我們常常稱之為「母對象」(Meta-object),而類別的靜態(tài)函數(shù)(static function)就是這個母對象的函數(shù),在這種函數(shù)里可以(由該母對象)創(chuàng)建自己類別的對象。在上圖的架構(gòu)里,由myActivity創(chuàng)建Player基類的init()靜態(tài)函數(shù),這init()創(chuàng)建其親生子類別mp3Player的對象。請留意,這init()會將mp3Player的IPlay接口傳回給myActivity。一旦myActivity接到mp3Player的IPlay接口,就能進行實際的創(chuàng)建動作。也就是,myActivity透過IPlay接口,而創(chuàng)建到mp3Player的play()函數(shù),并進而創(chuàng)建MediaPalyer的start()函數(shù),展開了播放mp3音樂的動作了。[歡迎光臨 高煥堂 網(wǎng)頁: http://www.cnblogs.com/myEIT/ ]
2. 框架的設(shè)計與實踐
2.1 復(fù)習:擅用配置文文件
在上一篇文章里,運用了配置(Configuration)文件的機制來實踐由框架(的基類)來創(chuàng)建應(yīng)用(AP或App)子類的對象的任務(wù),這是框架開發(fā)的基本技巧。其主要面對的情境是:框架基類由強龍設(shè)計在先,而應(yīng)用子類則由地頭蛇開發(fā)在后。也就是說,當強龍撰寫框架基類時,地頭蛇(和客戶)都尚未出現(xiàn),基類開發(fā)者還不知道AP子類的名稱,那么又如何去<<new>>一個AP子類的對象呢? 其實很簡單,因為在程序的執(zhí)行時間( Run-time)才會真正創(chuàng)建對象,這執(zhí)行時間已經(jīng)是在地頭蛇撰寫子類的時間之后了,如下圖所示:
圖4、由子類開發(fā)者撰寫配置(Configuration)文件
因此,解決之道是:請地頭蛇撰寫完AP子類時,也將子類的名稱字符串(classname string)寫入一個特定的配置(Configuration)文件里,然后于程序執(zhí)行時,才去讀取配置文文件里的子類的名稱字符串,然后透過Java的指令:
Class.forName(classname).newInstance();
就能創(chuàng)建該AP子類的對象了。于是,實踐了由框架創(chuàng)建AP子類對象的任務(wù)了。
2.2 設(shè)計架構(gòu)圖
基于上述配置文文件的機制,也依循上一篇文章范例的架構(gòu),茲繪制架構(gòu)圖如下:
圖6、由基類創(chuàng)建子類對象的過程
創(chuàng)建完成子類對象之后,就能夠透過接口來調(diào)用該子類對象的函數(shù)了。例如,myActivity就透過IPlay而調(diào)用mp3Player的play()函數(shù),此刻myActivity就調(diào)用MediaPlayer的start()函數(shù),開始播放了。如下圖:
圖7、調(diào)用所創(chuàng)建的新對象
結(jié)束播放時,myActivity就透過IPlay而調(diào)用了mp3Player的stop()函數(shù),此刻myActivity就調(diào)用MediaPlayer的stop()函數(shù)了。
2.3 撰寫代碼:<創(chuàng)建對象>的實踐途徑
茲將上圖落實為Android代碼,其執(zhí)行畫面如下:
首先建立一個Android的Ex04_02項目(Project),如下:
背景圖像sunrise.png存在/res里。
撰寫你的框架基類和API
// Player.java
package myFramework;
import android.content.Context;
public abstract class Player {
static private Player player = null;
public static IPlay init(Context context){
String pkclassName = ((PActivity)context).getPlayerClass();
try {
player = (Player)Class.forName(pkclassName).newInstance();
return (IPlay)player;
} catch (Exception e)
{ e.printStackTrace(); }
return null;
}
}
// PActivity.java
package myFramework;
import com.misoo.pk003.R;
import android.app.Activity;
public abstract class PActivity extends Activity{
public IPlay init(){
return Player.init(this);
}
public String getPlayerClass(){
return this.getResources().getString(R.string.playerclass);
}
}
// IPlay.java
package myFramework;
import android.content.Context;
public interface IPlay {
void play(Context context);
void stop();
}
把基類和API送人,協(xié)助別人去開發(fā)應(yīng)用子類
// mp3Player.java
package com.misoo.pk003;
import myFramework.IPlay;
import myFramework.Player;
import android.content.Context;
import android.media.MediaPlayer;
import android.util.Log;
public class mp3Player extends Player implements IPlay{
private MediaPlayer mPlayer = null;
public void play(Context context) {
try{
mPlayer = MediaPlayer.create(context, R.raw.dreamed);
mPlayer.start();
} catch (Exception e) {
Log.e("StartPlay", "error: " + e.getMessage(), e);
}
}
public void stop(){
if (mPlayer != null) {
mPlayer.stop(); mPlayer.release(); mPlayer = null;
}
}}
// myActivity.java
package com.misoo.pk003;
import myFramework.IPlay;
import myFramework.PActivity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
public class myActivity extends PActivity implements OnClickListener{
private Button ibtn1, ibtn2;
private IPlay player;
@Override protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
ibtn1 = new Button(this); ibtn1.setOnClickListener(this);
ibtn1.setText("Play"); ibtn1.setBackgroundResource(R.drawable.heart);
LinearLayout.LayoutParams param1 =
new LinearLayout.LayoutParams(150, 65);
param1.topMargin = 10; param1.leftMargin = 10;
layout.addView(ibtn1, param1);
ibtn2 = new Button(this); ibtn2.setOnClickListener(this);
ibtn2.setText("Exit"); ibtn2.setBackgroundResource(R.drawable.mountain);
layout.addView(ibtn2, param1);
setContentView(layout);
//-----------------------------------------------
player = init();
}
public void onClick(View v) {
if(v == ibtn1) {
setTitle("playing...");
player.play(this);
}
else {
player.stop();
finish();
}
}
3. 結(jié)語
由框架(的基類)來創(chuàng)建應(yīng)用(AP或App)子類的對象是框架開發(fā)的基本技巧。因為框架必需掌握重要對象的運行生命周期(Life-cycle)才能有效控制對象的行為,以及取重要的信息傳遞機制和內(nèi)容。如此,框架就能有效<框住>數(shù)以萬計的應(yīng)用程序,而不會失控了。◆
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。