ee ee
歡迎訪問 ==>高老師的博客網頁
高煥堂:MISOO(大數據.大思考)聯盟.臺北中心和東京(日本)分社.總教練
EE EE
您好,登錄后才能下訂單哦!
前言:
誰來誕生子類的對象呢? 答案是:框架。這樣讓框架能有絕對的制約能力去「框住」應用子類的結構和行為。接著,請你來思考一個有趣的問題:
l框架開發者(強龍)先寫框架基類的程序碼;
l然后,AP開發者(地頭蛇)才撰寫應用子類在后。
那么框架開發者事先又如何知道地頭蛇后來撰寫的應用子類的名稱呢? 如果不知道應用子類的名稱,又如何誕生應用子類的對象呢?
ee ee
歡迎訪問 ==>高老師的博客網頁
高煥堂:MISOO(大數據.大思考)聯盟.臺北中心和東京(日本)分社.總教練
EE EE
框架如何創建App子類的對象(二)?
--- 由基類創建親生子類的對象
1. 以MediaPlayer播放mp3音樂為例
大家對于拿MediaPlayer來播放mp3音樂的應用程序,應該不會陌生。最簡單的架構如下圖所示:
圖1、由myActivity來創建MediaPlayer的對象
你也可以設計一個包容器(Wrapper)類別來包裝MediaPlayer類別,也就是由這個Wrapper來幫忙創建MediaPlayer對象,如下圖所示:
圖2、由Wrapper協助來創建MediaPlayer的對象
無論是在上圖1或圖2的架構里,你都是扮演一個傳統的角色:AP開發者。于此,就來換個新鮮的角色:框架開發者。在上一篇文章里,已經說明了,必須讓框架基類去創建應用子類的對象,才能讓框架擁有高度的制約力量。在上一篇文章的范例里(即Ex04_01程序范例)已經實踐了這個目標,讓框架基類(如GraphView)來創建子類別(如myDrawing)的對象。其中,值得留意的是:上一篇文章范例里的基類GraphView并不是myDrawing的直系父類別(基類)。簡而言之,myDrawing并不是繼承GraphView基類。亦即,myDrawing并不是GraphView的親生應用子類。
于是,在本文里,我們來看看一個基類如何創建親生子類別的對象。如下圖所示:
圖3、由基類Player來創建親生子類mp3Player的對象
大家都知道一個類別本身就是一個對象,我們常常稱之為「母對象」(Meta-object),而類別的靜態函數(static function)就是這個母對象的函數,在這種函數里可以(由該母對象)創建自己類別的對象。在上圖的架構里,由myActivity創建Player基類的init()靜態函數,這init()創建其親生子類別mp3Player的對象。請留意,這init()會將mp3Player的IPlay接口傳回給myActivity。一旦myActivity接到mp3Player的IPlay接口,就能進行實際的創建動作。也就是,myActivity透過IPlay接口,而創建到mp3Player的play()函數,并進而創建MediaPalyer的start()函數,展開了播放mp3音樂的動作了。[歡迎光臨 高煥堂 網頁: http://www.cnblogs.com/myEIT/ ]
2. 框架的設計與實踐
2.1 復習:擅用配置文文件
在上一篇文章里,運用了配置(Configuration)文件的機制來實踐由框架(的基類)來創建應用(AP或App)子類的對象的任務,這是框架開發的基本技巧。其主要面對的情境是:框架基類由強龍設計在先,而應用子類則由地頭蛇開發在后。也就是說,當強龍撰寫框架基類時,地頭蛇(和客戶)都尚未出現,基類開發者還不知道AP子類的名稱,那么又如何去<<new>>一個AP子類的對象呢? 其實很簡單,因為在程序的執行時間( Run-time)才會真正創建對象,這執行時間已經是在地頭蛇撰寫子類的時間之后了,如下圖所示:
圖4、由子類開發者撰寫配置(Configuration)文件
因此,解決之道是:請地頭蛇撰寫完AP子類時,也將子類的名稱字符串(classname string)寫入一個特定的配置(Configuration)文件里,然后于程序執行時,才去讀取配置文文件里的子類的名稱字符串,然后透過Java的指令:
Class.forName(classname).newInstance();
就能創建該AP子類的對象了。于是,實踐了由框架創建AP子類對象的任務了。
2.2 設計架構圖
基于上述配置文文件的機制,也依循上一篇文章范例的架構,茲繪制架構圖如下:
圖6、由基類創建子類對象的過程
創建完成子類對象之后,就能夠透過接口來調用該子類對象的函數了。例如,myActivity就透過IPlay而調用mp3Player的play()函數,此刻myActivity就調用MediaPlayer的start()函數,開始播放了。如下圖:
圖7、調用所創建的新對象
結束播放時,myActivity就透過IPlay而調用了mp3Player的stop()函數,此刻myActivity就調用MediaPlayer的stop()函數了。
2.3 撰寫代碼:<創建對象>的實踐途徑
茲將上圖落實為Android代碼,其執行畫面如下:
首先建立一個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送人,協助別人去開發應用子類
// 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. 結語
由框架(的基類)來創建應用(AP或App)子類的對象是框架開發的基本技巧。因為框架必需掌握重要對象的運行生命周期(Life-cycle)才能有效控制對象的行為,以及取重要的信息傳遞機制和內容。如此,框架就能有效<框住>數以萬計的應用程序,而不會失控了。◆
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。