by 高煥堂 2013/06/20
一、EIT造形的涵意
自从1996年Java问世之后,接口(Interface)成为Java语言的关键词(Key Word)。于是,<接口>的位阶已经提升了,其与<类>是同位阶了,而不再隐藏于类造形里。这意味着,我们可以设计一个更大的代码造形来包容类和接口两种元素。为了凸显接口角色,就得考虑两项特性:
- 为了清楚地定义一个接口(主角),需要两个类来当配角。
- 此外,接口以能实现为类(造形)。
于是,高焕堂老师将3个<类造形>组合起来,成为一个更大的造形;就像生物DNA的螺旋结构,组合如下图:
在上图里,为于中间的类就是接口实现类。高老师将其命名为EIT造形:
EIT造形也不难理解,它只是对类造形加以扩大;也就是以类为基础(保留了类的各项功能),将3个类结合在一起,各扮演不同角色;让开发者拥有更大的视野,具有更好的整体观。例如,Java语言的程序:
class Tasks implements Runnable{
public void run() {
int sum = 0;
for (int i = 0; i <= 100; i++)
sum += i;
System.out.println("Result: " + sum);
}
}
// ----------------------------------------------------------
public class JMain {
public static void main(String[] args) {
Thread t = new Thread( new Tasks());
t.start();
System.out.println("Waiting...");
}
}
其主要意图是:凸显出<接口>元素与类同位阶的角色。为了清楚地定义一个接口(主角),需要两个类来当配角。例如,为了凸显Runnable接口,而且要精确地表述它,就需要Thread和Tasks两个类来陪衬,如下图:
由于接口定义是架构师的主要职责,所以EIT可以协助架构师清晰地定义接口,非常有助于清晰表达架构。
二、EIT造形的重复组合
EIT造形也内部结构简单,也能透过内含的类的组合关系,将EIT造形组合起来,轻易地组合出大型而复杂的系统。例如,EIT造形能像DNA螺旋结构一样,组合起来:
EIT造形提供更宏大的整体观,更易于重构,迅速从简单组合出复杂系统。
这是由两个EIT造形(即Thread造形和View造形)所组成的。
在游戏软件应用上,这个Thread造形里的小线程(由UI线程所诞生的)扮演一个特殊的角色:成为游戏的主控循环(Game Loop),而UI线程则专注于响应UI 的事件,创造出两个线程完美分工。由于这个线程专注于游戏主控循环,所以又称为游戏线程(Game Thread)。游戏线程调用postInvalidate()函数,间接触发UI线程去调用invalidate()函数了,也触发View重新调用App子类的onDraw()去重新绘图了。现在就将上图落实为Android程序码,如下:
// GameLoop.java
package com.misoo.pk001;
public class GameLoop implements Runnable {
myView mView;
GameLoop(myView v){
mView = v;
}
public void run() {
mView.doUpdate();
mView.postInvalidateDelayed(1000);
}
}
// myView.java
package com.misoo.pk001;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.View;
public class myView extends View {
private Paint paint= new Paint();
private int x, y;
private int line_x = 100;
private int line_y = 100;
private float count = 0;
myView(Context ctx)
{ super(ctx); }
public void doUpdate(){
if( count > 12) count = 0;
x = (int) (75.0 * Math.cos(2*Math.PI * count/12.0));
y = (int) (75.0 * Math.sin(2*Math.PI * count/12.0));
count++;
}
@Override protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.WHITE);
paint.setColor(Color.BLUE); paint.setStrokeWidth(3);
canvas.drawLine(line_x, line_y, line_x+x, line_y+y, paint);
paint.setStrokeWidth(2); paint.setColor(Color.RED);
canvas.drawRect(line_x-5, line_y - 5, line_x+5, line_y + 5, paint);
paint.setColor(Color.CYAN);
canvas.drawRect(line_x-3, line_y - 3, line_x+3, line_y + 3, paint);
Thread gt = new Thread(new GameThread(this));
gt.start();
}
}
// myActivity.java
package com.misoo.pk001;
import com.misoo.pk001.R;
import android.app.Activity;
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 Activity implements OnClickListener {
private myView mv = null;
private Button ibtn;
@Override protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
show_layout_01();
}
public void show_layout_01(){
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
mv = new myView(this);
LinearLayout.LayoutParams param =
new LinearLayout.LayoutParams(200, 200);
param.topMargin = 10;
param.leftMargin = 10;
layout.addView(mv, param);
//----------------------------------------------
ibtn = new Button(this);
ibtn.setOnClickListener(this);
ibtn.setText("Exit");
ibtn.setBackgroundResource(R.drawable.gray);
LinearLayout.LayoutParams param1 =
new LinearLayout.LayoutParams(200, 65);
param1.topMargin = 10; param1.leftMargin = 10;
layout.addView(ibtn, param1);
//-----------------------------------------------
setContentView(layout);
}
public void onClick(View v)
{ finish(); }
}
由于EIT造形只是对类造形加以扩大;也就是以类为基础(保留了类的各项功能),将3个类结合在一起,各扮演不同角色。所以,只要利用类造形既有的组合机制,就能将EIT造形组合起来,成为复杂的系统了。例如,也能组合如下图:
这通称为:双层EIT造形的架构设计。
三、为什么需要要有两个配角呢?
虽然从代码造形来看,<E>、<I>和<T>三者是同位阶的,但从架构师角度上,<I>属于主角,而<E>和<T>是配角。搭配两个配角,才能将<I>表述的完整而清晰。
搭配两个配角,就能将<I>表述的更完整而清晰。
拿英语来比喻
就如同英语,搭配了主词(Subject)和受词(Object),就能够将动词(Verb)表述得更完整而清晰。例如,
- play -- 没有主词和受词,动词<play>就显得意义不够清晰。
- 猫 玩(play) 绣球 -- 有了主词和受词,动词<play>就显得意义很清晰。
- 老师 弹(play) 钢琴 -- 有了主词和受词,动词<play>就显得意义很清晰。
拿厕所来比喻
依据传统的类造形,架构师会表述为:设计一个厕所类(对映到实际的厕所),其提供接口(实际厕所的入口)给男生或女生使用。这很可能引导开发者先建置厕所,然后才提供入口给用户使用;经常是先类而后接口。
反之,如果使用EIT造形,则架构师就表述为:(女生<E>、入口<I>、厕所<T>),以及<男生<E>、入口<I>、厕所<T>)。架构师考虑到女生和厕所,而定设计入口<Iw>,然后交给开发者去撰写<Tw>代码。同样地,架构师考虑到男生和厕所,而定设计入口<Im>,然后交给开发者去撰写<Tm>代码。架构师设计出来的<Iw>和<Im>是不一样的;同理,开发者撰写的<Tw>和<Tm>也是不一样的。架构师与开发者的沟通变得清晰而完整。这有效引导架构师先定义明确的<I>,然后提醒架构师搭配<E>和<T>来表述<I>。