by 高煥堂

认识接口(Interface)设计


1.两种接口:主动型与被动型 

就软件主板(MB)设计(开发)者而言,反向调用的接口(如<I>)能让主板获得主控权,所以又称为主动型接口或强势型接口。而正向调用的接口(如CI接口)则让子类或Client类获得主控权,所有(从主板视角而言)又称为被动型接口。

无论是主动型或被动型接口都是主板的基类(或称为父类)所提供的,但是这两种接口对于子类(或Client类)的制约能力并不相同,主动型接口让基类具有强大的制约能力(所以称为强势接口),可以主导子类的结构和行为;而被动型接口则不能带给(主板的)基类任何制约或主导力量。因此,分辨主动型与被动型API的区别,是极为重要的能力。两者可藉由3个攸关的动词来区别之:

1. 定义(Define)

     2. 实现(Implement)

     3. 调用(Invoke or Call)


根据这3个角度,可将接口区分为「主动型」与「被动型」两种,如下表:

兹举Android的IPC主板模式为例,这软件主板里就含有两种接口,如下图所示:

其中,Binder基类的具象函数transact()调用onTransact()抽象函数,就反向调用到子类myBinder的onTransact()函数了。关于onTransact()抽象函数:

l  定义于基类

l  实现于子类

l  让基类来调用子类的实现

l  所以,对基类而言,它属于主动型接口

关于的transact()具象函数:

l  定义于基类

l  实现于基类

l  让其它Client类(别)来调用

l  所以,对基类而言,它属于被动型接口

如下图所示:

1.2 说明两种API的制约力量

   所谓被动型接口就是,相对而言,基类处于被主导(Dominated)的地位,也就是说,被子类或其它Client类所主导了。如下图:

上述execute()函数所构成的CI接口,其制约力量强弱程度比率为:

 基类:子类  è  0.4 : 0.6

  再看看主动型的接口,相对而言,基类处于主导(Dominate)的地位,也就是说,基类主导了子类。例如,上述onTransact()函数所构成的<I>接口,其制约力量强弱程度比率为:  就软件主板(MB)设计(开发)者而言,反向调用的接口(如<I>)能让主板获得主控权,所以又称为主动型接口或强势型接口。而正向调用的接口(如CI接口)则让子类或Client类获得主控权,所有(从主板视角而言)又称为被动型接口。

    基类:子类  è  0.8 : 0.2

  就此接口而言,基类具有高度的制约力量可主导子类。将上述的比率,配到上图里的主板模式里。兹进一步说明如下:

  • Client调用主板的execute()具象函数,属于主板的被动型接口,主板的制约力量只有0.4(比率是0.4:0.6)。

  • 主板调用子类的onTransact()函数,属于框架的主动型接口,框架的制约力量有0.8(比率是0.8:0.2)。

  • 所以,整体上而言,主板拥有制高点(即主导性)。所以才称之为<主板>。

以上说明了主板的两种接口。其中的主动型接口是最为重要的,因为它是实践主板的主控权的关键所在。

1.3 演练:分辨主动型与被动型接口

1.3.1 演练(一)

许多App开发者是基于Android提供的基类来撰写App子类,然后与基类结合起来编译(Compile)和连结(Link)成为可执行的App。如下图:

在此图里可以看到,Android基类View定义了onDraw()函数,它是一个可覆写的(Overridable)函数。于是,你就可以撰写一个子类(如上图里的myView),并覆写onDraw()函数。在程序执行时,基类就能反向调用到子类的onDraw()函数了。

演练问题:关于上图的onDraw()函数,属于基类(View)的主动型接口? 还是被动型接口呢?

1.3.2 演练(二)

相信你已经扮演过上述的传统角色了。现在,您可以试试转换到一个全新的角色,飞上枝头变凤凰了。也就是从原来的App开发者,转变成为主板开发者。这个新鲜的角色就是:开发自己的主板基类和接口。首先设计一个View的子类别,设其名称为 GraphView。虽然它是View的子类别,也覆写了onDraw()函数;但是它又提供了一个可覆写的函数:doDraw();可让应用子类来覆写之。如下图所示:

上图里的GraphView基类定义了一个可覆写的doDraw()函数,它可画出背景图像。执行时,GraphView的onDraw()函数调用其doDraw()函数。由于子类覆写了doDraw()函数,所以onDraw()会转而调用BirdView子类的doDraw()函数。此时,子类的doDraw()可以先调用基类GraphView的doDraw()去先画出背景,然后返回BirdView的doDraw()函数绘出前景图像。在GraphView里,其doDraw()函数里含有指令来画背景,这就是所谓的「预设行为」,子类别的doDraw()函数只要调用它,就能画出背景了;这可以减轻子类别的负担。

练问题:关于上图的doDraw()函数,属于GraphView的主动型接口? 还是被动型接口呢?

1.3.3 演练(三)

当然还可以设计出其它的结构,例如可以将上述的预设行为独立出来成为一个新的函数,如取名为drawBackgraound()函数。此时,doDraw()就变成一个抽象函数了。如下图所示:

演练问题:关于上图的drawBackground()函数,属于GraphView2的主动型接口? 还是被动型接口呢?

1.3.4 演练(四)

当然还可以设计出其它的结构,例如下图:

   在这个结构里,是由基类GraphView2的onDraw()先调用drawBackground()函数来画出背景图像,然后才调用其doDraw()抽象函数,就转而返像调用了子类别BirdView的onDraw()函数来画出前景图像。

演练问题:关于上图的doDraw()函数,属于GraphView2的主动型接口? 还是被动型接口呢?

1.3.5 演练(五)

当然还可以设计出其它的结构,例如下图:

此结构是是由基类GraphView3的onDraw()先调用drawBackground()函数来画出背景图像,然后才调用IDraw接口的doDraw()抽象函数,就转而返像调用了子类别BirdDrawing的onDraw()函数来画出前景图像。


演练问题:关于上图的IDraw接口(内含doDraw()函数),属于GraphView3的主动型接口? 还是被动型接口呢?

1.4 将设计落实为程序码

 在上一节里,我们说明了传统AP开发者的则职责就是设计应用子类别。于此,我们来复习一下传统的角色,实际从基类View衍生出一个应用子类:myView,并写出其程序码。接下来的本节里,我们将变换一个角色,从传统的AP开发者摇身一变而成为框架的设计者或开发者。于是,就必须自己来设计框架的基类和接口了。

l  设计架构图

这个程序的结构,就如下图所示:

这个范例共含三层,其中包括:两层框架和一层AP。上层框架是Google所开发的,而第二层框架是我们所开发的。上层框架里的View基类会反向调用到GraphView的onDraw()函数,接着onDraw()先调用自己的drawBackground()函数去绘制背景图案(本范例是绘出空白背景),然后调用IDraw接口的doDraw()函数,汇出一只蓝色的精灵飞侠。如下图所示:

l  撰写程序码

首先建立一个Android的项目,如下:

★ 撰写你的基类和接口

// GraphView.java

package Framework;

import android.content.Context;

import android.graphics.Canvas;

import android.graphics.Color;

import android.view.View;

publicclass GraphView extends View{

private IDraw fgDrawer;

public GraphView(Context context) {

super(context);

}

@Override

 protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

this.drawBackground(canvas);

fgDrawer.doDraw(canvas);

}

protected void drawBackground(Canvas canvas){

canvas.drawColor(Color.WHITE);

}

public void setForegroundDrawer(IDraw fgd){

fgDrawer = fgd;

}

}

// IDraw.java

package Framework;

import android.graphics.Canvas;

publicinterface IDraw {

voiddoDraw(Canvas canvas);

}

★ 把基类和接口送人,协助别人去开发应用子类

// myDrawing.java

package com.misoo.pk001;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.Paint;

import android.graphics.RectF;

import Framework.IDraw;

public class myDrawing implements IDraw {

private Paint paint;

myDrawing()

{  paint= new Paint(); }

public void doDraw(Canvas canvas) {

paint.setAntiAlias(true);

RectF rectF = new RectF(80,110,180,180);

paint.setColor(Color.BLUE);

canvas.drawArc(rectF, 220, 180,true, paint);

paint.setStrokeWidth(3);

canvas.drawLine(135,120, 140, 75, paint);

canvas.drawLine(160, 140, 210, 130, paint);

paint.setColor(Color.WHITE);

canvas.drawCircle(128, 125, 6, paint);

canvas.drawCircle(162, 145, 6, paint);

}

}

// myActivity.java

package com.misoo.pk001;

import Framework.GraphView;

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;

publicclass myActivity extends Activity implements OnClickListener {

private GraphView mv = null;

private Button ibtn;

@Override

     protected void onCreate(Bundle icicle) {

super.onCreate(icicle);

LinearLayout layout = new LinearLayout(this);

layout.setOrientation(LinearLayout.VERTICAL);

mv = new GraphView(this);

LinearLayout.LayoutParams param =

new LinearLayout.LayoutParams(250, 280);

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(100, 65);

param1.topMargin = 10;

param1.leftMargin = 10;

layout.addView(ibtn,param1);

setContentView(layout);

//-----------------------------------------------

mv.setForegroundDrawer(new myDrawing());

}

public void onClick(View v)

{  finish();  }

}

~ End ~

转载于:https://blog.51cto.com/8204129/1708189

认识接口(Interface)设计相关推荐

  1. (20)System Verilog接口interface设计示例

    (20)System Verilog接口interface设计示例 1.1 目录 1)目录 2)FPGA简介 3)System Verilog简介 4)System Verilog接口interfac ...

  2. Go 学习笔记(35)— Go 接口 interface (接口声明、接口初始化、接口方法调用、接口运算、类型断言、类型查询、空接口)

    1. 接口概念 接口是双方约定的一种合作协议.接口实现者不需要关心接口会被怎样使用,调用者也不需要关心接口的实现细节.接口是一种类型,也是一种抽象结构,不会暴露所含数据的格式.类型及结构. 接口内部存 ...

  3. 谈谈Java接口Result设计

    这篇文章酝酿了很久,一直想写,却一直觉得似乎要讲的东西有点杂,又不是很容易讲清楚,又怕争议的地方很多,就一拖再拖.但是,每次看到不少遇到跟这个设计相关导致的问题,又忍不住跟人讨论,但又很难一次说清楚, ...

  4. 面向对象之内置方法(简单)、组合。以及接口归一化设计与抽象类

    一.内置方法 一 isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的对象 class Foo( ...

  5. Java接口(interface)的概念及使用

    在抽象类中,可以包含一个或多个抽象方法:但在接口(interface)中,所有的方法必须都是抽象的,不能有方法体,它比抽象类更加"抽象". 接口使用 interface 关键字来声 ...

  6. java 抽象接口类,Java接口(interface)和Java抽象类(abstract class)的区别(详诉版)

    1.概述 一个软件设计的好坏,我想很大程度上取决于它的整体架构,而这个整体架构其实就是你对整个宏观商业业务的抽象框架, 当代表业务逻辑的高层抽象层结构合理时,你底层的具体实现需要考虑的就仅仅是一些算法 ...

  7. 组件接口(API)设计指南-文件夹

    组件接口(API)设计指南-文件夹 组件接口(API)设计指南[1]-要考虑的问题 组件接口(API)设计指南[2]-类接口(class interface) 组件接口(API)设计指南[3]-托付( ...

  8. [转载]PSCAD调用MATLAB/SIMULINK之接口元件设计

    原文地址:PSCAD调用MATLAB/SIMULINK之接口元件设计作者:luckyhappier 1)接口元件 接口元件包括Graphics,Parameters和Script.注意:变量要与DSD ...

  9. 分布领域驱动设计(DDD):领域接口化设计式缓存的选择

    -     前言    - 把服务对象(service)和资源库对象(repository)设计成接口是最常见的.但是这对接口化的认识还远远不够,我们需要更深入地去分析接口化设计和更全面地应用接口化编 ...

  10. 开发日记:接口开发设计

    接口开发使用规则 业务术语: 请求:通过HTTP协议把需要传输的数据发送给接收方的过程. 返回:根据得到的数据处理完成后,将处理完成的结果反馈给接收方. 敏感词:带有敏感政治倾向,暴力倾向,不健康色彩 ...

最新文章

  1. cacti监控linux和windows磁盘IO
  2. 5GS 协议栈 — PFCP 协议 — MAR 多接入规则
  3. 如何查找cvpr类的论文_如何查找期刊论文?(3个实用的方法)
  4. SD-SD用到的文本对象列表
  5. h5页面禁止复制_网页禁止鼠标右键禁止全选复制粘贴的方法
  6. linux内核安装教程,Linux内核5.9的最重要功能及安装方法
  7. 外媒:苹果已有条件批准京东方为iPhone 13供应OLED屏幕
  8. recvfrom函数 非阻塞_那些年让你迷惑的阻塞、非阻塞、异步、同步
  9. 《C专家编程》阅读笔记
  10. 如何利用手机的OCR文字识别功能制作扫描件?
  11. QQ这个版本已经绝版。
  12. HM-A300小程序安卓打印异常
  13. OpenJudge百炼习题解答(C++)--题4108:羚羊数量-Number Of Antelope
  14. Unity - 九宫格切图报错
  15. linux usb gadget驱动详解(一)
  16. 66W真的比60W充电更快吗?基于Charge pump Charger的快充方案分析
  17. 在线配资的诀窍是什么?
  18. 为Ubuntu安装Realtek的无线网卡驱动
  19. Python3.6 车牌识别代码源码
  20. 侠探锦毛鼠之真假白玉堂

热门文章

  1. 那些年我们看不懂的论文
  2. vue 通信PHP,Vue组件通信(详细教程)
  3. c语言中x的n次方怎么表示_为什么一定要慎用C语言标准库中的pow函数,你知道吗?...
  4. Python爬虫入门学习线路图2019最新版
  5. Shark简介、部署及编译小结
  6. npm 常见用法小结
  7. Fresco几处不太好的地方
  8. iBatis.Net系列(五)-providers.config-
  9. 利用token 防止表单重复提交
  10. MonoCSharp Evaluator Extension