任何实现代码的方法都没有美丑之分,只有复杂与简单之分,人们喜欢简单的,害怕、厌烦、排斥复杂的。
设计模式之美就体现在可以把复杂的东西简单化,让人们用起来很简单,不再惧怕复杂,这就是设计模式美的体现。
Android框架乍一看很复杂,实际上应用了很多设计模式,所以如果我们从设计模式角度来分析Android框架,也就很简单了。
public class AA { private String x; AA(String str){ x = str; } public void print(){ System.out.println(x); } } public class BB { private int x; BB(int k){ x = k; } public void print(){ System.out.println(x); } } public class JMain { public static void main(String[] args) { AA a = new AA("hello"); BB b = new BB("hello girl"); a.print(); b.print();}}
下面就应用“变与不变的原则”,来优化上面的案例。
private String x; public final void template_print() { System.out.println( hook_getData() ); } public String hook_getData() { return x; } private int x; public final void template_print() { System.out.println( hook_getData() ); } public String hook_getData() { return String.valueOf(x); }
分离之后,template_print()函数含有不变的部分,而hook_getData()函数会含有变得部分。
接着再引入父子继承关系,将不变的template_print()函数提到父类中。
在父类中,定义抽奖的hook_getData()卡榫函数。
在父类中,在template_print()函数中调用抽象的卡榫函数hook_getData(),此时由继承机制反向(一般认为由子类调用父类的方法为正向)呼叫子类别的hook_getData()函数,实现了父、子类别之间的不同调用。
相对于Android框架来讲,temlate_print()函数将会吸收在框架里,hook_getData()函数将会被纳入到应用程序里。
这就是框架与应用程序之间的沟通了,hook_getData()卡榫函数起着桥梁的作用。
程序如下:
public abstract class SuperAB { public void template_print(){ System.out.println(hook_getData()); } protected abstract String hook_getData(); } public class AA extends SuperAB{ private String x; AA(String str){ x = str; } @Override protected String hook_getData() { return x; }} public class BB extends SuperAB{ private int x; BB(int k){ x = k; } @Override protected String hook_getData() { return String.valueOf(x); }} public class JMain { public static void main(String[] args) { AA a = new AA("hello"); a.template_print(); }}
public class ac01 extends Activity implements View.OnClickListener { private final int WC = LinearLayout.LayoutParams.WRAP_CONTENT; private final int FP = LinearLayout.LayoutParams.FILL_PARENT; private static ac01 appRef = null; private myButton btn, btn2, btn3; public TextView tv; private IBinder ib; public static ac01 getApp() { return appRef; } public void btEvent(String data) { setTitle(data); } public void onCreate(Bundle icicle) { super.onCreate(icicle); appRef = this; LinearLayout layout = new LinearLayout(this); layout.setOrientation(LinearLayout.VERTICAL); btn = new myButton(this); btn.setId(101); btn.setText("play"); btn.setOnClickListener(this); LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(btn.get_width(), btn.get_height()); param.topMargin = 10; layout.addView(btn, param); btn2 = new myButton(this); btn2.setId(102); btn2.setText("stop"); btn2.setOnClickListener(this); layout.addView(btn2, param); btn3 = new myButton(this); btn3.setId(103); btn3.setText("exit"); btn3.setOnClickListener(this); layout.addView(btn3, param); tv = new TextView(this); tv.setTextColor(Color.WHITE); tv.setText("Ready"); LinearLayout.LayoutParams param2 = new LinearLayout.LayoutParams(FP, WC); param2.topMargin = 10; layout.addView(tv, param2); setContentView(layout); bindService(new Intent(ac01.this, mp3Service.class), mConnection, Context.BIND_AUTO_CREATE); } private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder ibinder) { ib = ibinder; } public void onServiceDisconnected(ComponentName className) { } }; public void onClick(View v) { switch (v.getId()) { case 101: tv.setText("Playing audio..."); setTitle("MP3 Music"); try { ib.transact(1, null, null, 0); } catch (RemoteException e) { e.printStackTrace(); } break; case 102: tv.setText("Stop"); try { ib.transact(2, null, null, 0); } catch (RemoteException e) { e.printStackTrace(); } break; case 103: finish(); break; } } }
public class mp3Service extends Service { private IBinder mBinder = null; @Override public void onCreate() { mBinder = new mp3PlayerBinder(getApplicationContext()); } @Override public IBinder onBind(Intent intent) { return mBinder; } }
public class mp3PlayerBinder extends Binder { private MediaPlayer mPlayer = null; private Context ctx; public mp3PlayerBinder(Context cx) { ctx = cx; } @Override public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws android.os.RemoteException { if (code == 1) this.play(); else if (code == 2) this.stop(); return true; } public void play() { if (mPlayer != null) return; mPlayer = MediaPlayer.create(ctx, 0); try { mPlayer.start(); } catch (Exception e) { Log.e("StartPlay", "error: " + e.getMessage(), e); } } public void stop() { if (mPlayer != null) { mPlayer.stop(); mPlayer.release(); mPlayer = null; } } }
public class myButton extends Button { public myButton(Context ctx) { super(ctx); } public int get_width() { return 80; } public int get_height() { return 50; } }