MPAndroidChart Wiki(译文)~Part 1
1. 基础入门
1.1 添加依赖
Gradle 工程添加依赖 (推荐使用)
项目级build.gradle中添加:
allprojects {
repositories {
maven { url "https://jitpack.io" }
}
}
App下的 build.gradle中添加:
dependencies {
compile 'com.github.PhilJay:MPAndroidChart:v3.0.2'
}
Maven
pom.xml中添加如下repositories:
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
pom.xml中添加如下dependencies
<dependency>
<groupId>com.github.PhilJay</groupId>
<artifactId>MPAndroidChart</artifactId>
<version>v3.0.2</version>
</dependency>
直接使用Jar包文件
下载最新的.jar包,拷贝下载的文件到你的Android项目libs文件夹下然后开始使用这个开源库。
拷贝整个工程
使用git clone https://github.com/PhilJay/MPAndroidChart.git 命令下载整个工程,这个工程包含sample和MPChartLib库,然后你可以将这个库引入到你的Android Studio工程或者是Eclipse工程。
1.2 创建View
要使用LineChart, BarChart, ScatterChart, CandleStickChart, PieChart, BubbleChart 或者 RadarChart,我们可以首先在布局XML文件中定义它 :
<com.github.mikephil.charting.charts.LineChart
android:id="@+id/chart"
android:layout_width="match_parent"
android:layout_height="match_parent" />
然后我们可以在Fragment,Activity或者其他能拿到它的地方取到对象:
// in this example, a LineChart is initialized from xml
LineChart chart = (LineChart) findViewById(R.id.chart);
或者我们直接在代码中创建Chart然后把它添加到布局中去:
// programmatically create a LineChart
LineChart chart = new LineChart(Context);
// get a layout defined in xml
RelativeLayout rl = (RelativeLayout) findViewById(R.id.relativeLayout);
rl.add(chart); // add the programmatically created chart
1.3 添加数据
当你创建了一个chart实例后,你可以生成一些数据然后把它加入到图表中去。下面的例子中我们以LineChart为例,对LineChart而言,Entry类代表有X和Y值的图表中的一个条目。对于其他的Chart类型,如BarChart,你可以使用BarEntry作为数据条目。
为了给你的图表添加数据,你需要想下面这样将你的数据封装成Entry:
YourData[] dataObjects = ...;
List<Entry> entries = new ArrayList<Entry>();
for (YourData data : dataObjects) {
// turn your data into Entry objects
entries.add(new Entry(data.getValueX(), data.getValueY()));
}
下一步,你需要将List< Entry>添加到LineDataSet对象中。DataSet对象包含属于一组的数据,并且每个数据有自己独立的风格。如下“Label”只有描述目的如果设置enabled的话,它将会在Legend中显示出来。
LineDataSet dataSet = new LineDataSet(entries, "Label"); // add entries to dataset
dataSet.setColor(...);
dataSet.setValueTextColor(...); // styling, ...
最后一步,添加LineDataSet到LineData中,LineData包含对应Chart中的所有数据,并且我们可以更深入的定制数据的显示风格。在创建了数据之后我们将其加入到chart中然后刷新一下。
LineData lineData = new LineData(dataSet);
chart.setData(lineData);
chart.invalidate(); // refresh
上面这些都是很基本的设置和使用。更细节的介绍请查阅setting Data章节—- 结合示例的为你讲解如何给各式各样的图表添加数据。
1.4 样式
想要了解chart和数据的设置和样式,请查阅settings & styling章节。对于各种类型的数据和样式,请查阅specific settings & stylingwiki页面。
2. Chart交互
MPAndroidChart允许用户完成自定义于Chart View的触摸或者是手势事件,并且通过回调方法响应交互。
2.1 启用/禁用交互
方法 | 作用 |
---|---|
setTouchEnabled(boolean enabled) | 启用或者禁用触摸交互 |
setDragEnabled(boolean enabled) | 启用或者禁用拖拽交互 |
setScaleEnabled(boolean enabled) | 启用或者禁用缩放交互(X轴和Y轴) |
setScaleXEnabled(boolean enabled) | 启用或者禁用X轴缩放交互 |
setScaleYEnabled(boolean enabled) | 启用或者禁用Y轴缩放交互 |
setPinchZoom(boolean enabled) | 设置为true,则可以使用捏缩放,否则X轴Y轴将会分开缩放 |
setDoubleTapToZoomEnabled(boolean enabled) | 设置为false,双击放大功能将会被禁用 |
2.2 图表Fling和减速(针对滑动操作)
方法 | 作用 |
---|---|
setDragDecelerationEnabled(boolean enabled) | 如果设置为true,滑动操作完成后图表还会继续滚动。默认值为true |
setDragDecelerationFrictionCoef(float coef) | 减速摩擦系数在[0; 1]间隔,较高的值表示速度将缓慢降低,例如,如果设置为0,它将立即停止。 1是无效值,将自动转换为0.9999。 |
2.3 高亮值
如何通过点击手势高亮数据条目,请查阅highlighting section
2.4 手势回调
OnChartGestureListener接口可以让我们定义手势响应事件
public interface OnChartGestureListener {
/**
* Callbacks when a touch-gesture has started on the chart (ACTION_DOWN)
*
* @param me
* @param lastPerformedGesture
*/
void onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture);
/**
* Callbacks when a touch-gesture has ended on the chart (ACTION_UP, ACTION_CANCEL)
*
* @param me
* @param lastPerformedGesture
*/
void onChartGestureEnd(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture);
/**
* Callbacks when the chart is longpressed.
*
* @param me
*/
public void onChartLongPressed(MotionEvent me);
/**
* Callbacks when the chart is double-tapped.
*
* @param me
*/
public void onChartDoubleTapped(MotionEvent me);
/**
* Callbacks when the chart is single-tapped.
*
* @param me
*/
public void onChartSingleTapped(MotionEvent me);
/**
* Callbacks then a fling gesture is made on the chart.
*
* @param me1
* @param me2
* @param velocityX
* @param velocityY
*/
public void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY);
/**
* Callbacks when the chart is scaled / zoomed via pinch zoom gesture.
*
* @param me
* @param scaleX scalefactor on the x-axis
* @param scaleY scalefactor on the y-axis
*/
public void onChartScale(MotionEvent me, float scaleX, float scaleY);
/**
* Callbacks when the chart is moved / translated via drag gesture.
*
* @param me
* @param dX translation distance on the x-axis
* @param dY translation distance on the y-axis
*/
public void onChartTranslate(MotionEvent me, float dX, float dY);
}
简单地在类中实现上面这个接口,然后设置到对应的chart对象
chart.setOnChartGestureListener(this);
3. 高亮
本节重点介绍通过点击手势和基于版本v3.0.0以编程方式突出显示图表中的条目的主题。
3.1 启用/禁用高亮
方法 | 作用 |
---|---|
setHighlightPerDragEnabled(boolean enabled) | 在图表上将其设置为true,以便在完全缩小时在图表上拖动时突出显示。 默认值:true |
setHighlightPerTapEnabled(boolean enabled) | 在图表上将其设置为false可防止点击手势突出显示值。 仍然可以通过拖动或以编程方式突出显示值。 默认值:true |
setMaxHighlightDistance(float distanceDp) | 设置最大高亮距离(dp)。 图表上条目大于这个距离不会触发高亮。 默认值:500dp |
除此之外,单独的DataSet也能配置高亮:
dataSet.setHighlightEnabled(true); // allow highlighting for DataSet
// set this to false to disable the drawing of highlight indicator (lines)
dataSet.setDrawHighlightIndicators(true);
dataSet.setHighlightColor(Color.BLACK); // color for highlight indicator
// and more...
3.2 代码实现高亮
方法 | 作用 |
---|---|
highlightValue(float x, int dataSetIndex, boolean callListener) | 突出显示给定DataSet中指定x位置的值。 dataSetIndex为-1时撤消所有高亮。 callListener决定了是否调用选择监听器。 |
highlightValue(Highlight high, boolean callListener) | 突出显示由提供的高光对象表示的值。 提供null以撤销所有突出显示。 callListener决定了是否调用选择监听器。 |
highlightValues(Highlight[] highs) | 突出显示highs代表的高光对象表示的值。提供null或者是空数组取消所有高亮 |
getHighlighted() | 以highlight[]的形式返回包含所有高光条目信息,X坐标,DateSet索引 |
3.3 选择回调
开源库提供了大量用来处理交互的监听器。OnChartValueSelectedListener是其中一个,用来处理通过触摸高亮数据条目时处理回调:
public interface OnChartValueSelectedListener {
/**
* Called when a value has been selected inside the chart.
*
* @param e The selected Entry.
* @param h The corresponding highlight object that contains information
* about the highlighted position
*/
public void onValueSelected(Entry e, Highlight h);
/**
* Called when nothing has been selected or an "un-select" has been made.
*/
public void onNothingSelected();
}
在需要接受回调的类中实现上面这个接口,然后将监听器设置到Chart即可
chart.setOnChartValueSelectedListener(this);
3.4 Highlight类
Hightlight类代表一个高亮条目的所有数据,如高亮条目本身,它的DataSet,它在界面上的绘制位置等等。这个类可以用来得到当前高亮条目的信息,或者用来告诉Chart,需要高亮哪些条目。为了实现这些目的,Highlight类提供了两个构造方法:
/** constructor for standard highlight */
public Highlight(float x, int dataSetIndex) { ... }
/** constructor for stacked BarEntry highlight */
public Highlight(float x, int dataSetIndex, int stackIndex) { ... }
通过构造函数你可以创建Hightlight对象,然后通过代码的方式实现高亮:
// highlight the entry and x-position 50 in the first (0) DataSet
Highlight highlight = new Highlight(50f, 0);
chart.highlightValue(highlight, false); // highlight this value, don't call listener
3.5 自定义高亮器
所有以高亮手势形式显示的用户输入都由默认的ChartHighlighter类进行内部处理。 使用以下方法可以用自定义实现替换默认的highligher:
方法 | 作用 |
---|---|
setHighlighter(ChartHighlighter highlighter) | 设置一个自定义高亮器来处理所有图表上的高亮事件。你的自定义高亮器必须继承ChartHighlighter类 |
4. 轴
该wiki页面重点介绍AxisBase类,XAxis(XAxis)和YAxis(YAxis)的基础类。 在v2.0.0中引入
下面提到的以下方法都可以应用于两个轴。
- 轴类允许特定的样式,包括以下组件/部件(可以包括):
标签(以垂直(y轴)或水平(x轴)对齐绘制),其中包含轴描述值 - 所谓的“轴线”被直接绘制在标签附近并与标签平行
- “网格线”,各自源自水平方向的轴标签
- 限制线,允许呈现特殊信息,如边界或约束
4.1 控制轴线绘制(哪些部分需要绘制)
方法 | 作用 |
---|---|
setEnabled(boolean enabled) | 设置轴启用或禁用。 如果禁用,无论任何其他设置如何,都不会绘制轴的任何部分 |
setDrawLabels(boolean enabled) | 将其设置为true可以绘制轴的标签。 |
setDrawAxisLine(boolean enabled) | 如果沿着轴(轴线)的线应该被绘制,则将其设置为true。 |
setDrawGridLines(boolean enabled) | 将其设置为true可以绘制轴的网格线。 |
4.2 自定义轴的范围(最小值/最大值)
方法 | 作用 |
---|---|
setAxisMaximum(float max) | 设置此轴的自定义最大值。 如果设置,此值将不会根据提供的数据自动计算. |
resetAxisMaximum() | 调用此方法来撤销先前设置的最大值。 通过这样做,你将再次允许轴自动计算它的最大值。 |
setAxisMinimum(float min) | 设置此轴的自定义最小值。 如果设置,此值将不会根据提供的数据自动计算 |
resetAxisMinimum() | 调用此方法来撤销先前设置的最小值。 通过这样做,你将再次允许轴自动计算它的最小值。 |
setStartAtZero(boolean enabled) | 已弃用 - 请使用setAxisMinValue(…)或setAxisMaxValue(…) |
setInverted(boolean enabled) | 如果设置为true,则该轴将被反转,这意味着最高值将在底部,最低值在顶部 |
setSpaceTop(float percent) | 设置图表中最高值的顶部间距(以总轴的百分比表示)与轴上的最高值相比较 |
setSpaceBottom(float percent) | 设置图表中最低值的底部间距(以总轴范围的百分比表示)与轴上的最低值相比较. |
setShowOnlyMinMax(boolean enabled) | 如果启用,该轴将仅显示其最小值和最大值。 这将忽略/覆盖定义的标签计数(如果不强制). |
setLabelCount(int count, boolean force) | 设置y轴的标签数量。 请注意,这个数字不是固定的(如果force == false),并且只能近似。 如果强制启用(true),则绘制精确的指定标签计数 - 这可能导致轴上的数字不均匀。 |
setPosition(YAxisLabelPosition pos) | 设置绘制轴标签的位置。 INSIDE_CHART或OUTSIDE_CHART。 |
setGranularity(float gran) | 设置y轴值之间的最小间隔。 这可以用于在放大到为轴设置的小数位数不再允许区分两个轴值的点时避免重复值。 |
setGranularityEnabled(boolean enabled) | 启用在放大时限制y轴间隔的粒度特征。默认值:false |
4.3 样式/修改轴
方法 | 作用 |
---|---|
setTextColor(int color) | 设置轴标签的文字颜色. |
setTextSize(float size) | 设置轴标签的文字大小(dp) |
setTypeface(Typeface tf) | 设置轴标签的字体 |
setGridColor(int color) | 设置轴网格线的颜色 |
setGridLineWidth(float width) | 设置轴网格线的宽度 |
setAxisLineColor(int color) | 设置轴线的颜色 |
setAxisLineWidth(float width) | 设置轴线的宽度 |
enableGridDashedLine(float lineLength, float spaceLength, float phase) | 使网格线以虚线模式绘制,例如”- - - - - -”。 “lineLength”控制线段的长度,“spaceLength”控制线间的空间,“phase”控制起点。 |
4.4 格式化轴值
对于格式化轴值,可以使用IAxisValueFormatter接口,你可以使用axis.setValueFormatter(IAxisValueFormatter formatter)方法将自定义格式设置到轴,具体请查阅here
4.5 限制值
两个轴都支持所谓的LimitLine,允许提供特殊信息,如边界或约束。 添加到YAxis的LimitLines在水平方向绘制,并且在添加到XAxis时在垂直方向绘制。 下面介绍如何从轴中添加和删除LimitLines:
方法 | 作用 |
---|---|
addLimitLine(LimitLine l) | 给轴添加一条LimitLine |
removeLimitLine(LimitLine l) | 移除轴上一条指定的LimitLine |
还有很多添加/移除的方法 | |
setDrawLimitLinesBehindData(boolean enabled) | 允许控制LimitLines和实际数据之间的z顺序。 如果将此设置为true,则LimitLine将在实际数据之后绘制,否则在顶部。 默认值:false |
限制线(LimitLine类)(正如名称可能指示的),可以使用简单线条为用户提供附加信息。
例如,你的图表可能会显示用户使用应用程序记录的各种血压测量结果。 为了通知用户超过140 mmHg的收缩压被认为是健康风险,您可以在140处添加LimitLine来提供该信息。
4.6 示例代码
YAxis leftAxis = chart.getAxisLeft();
LimitLine ll = new LimitLine(140f, "Critical Blood Pressure");
ll.setLineColor(Color.RED);
ll.setLineWidth(4f);
ll.setTextColor(Color.BLACK);
ll.setTextSize(12f);
// .. and more styling options
leftAxis.addLimitLine(ll);
5. X轴
XAxis是AxisBase的子类,它继承了许多样式和方法。
XAxis类(在2.0.0之前的版本中称为 XLabels),是与横轴有关的所有数据和信息容器。 每个Line-,Bar-,Scatter-,CandleStick-和RadarChart都有一个XAxis对象。
XAxis类允许特定的样式,包括以下组件(可以包括)以下组件/部件:
- 所谓的“轴线”被直接绘制在标签附近并与标签平行
- “网格线”,各自源于垂直方向的轴标签
通过如下方式获取XAxis实例:
XAxis xAxis = chart.getXAxis();
5.1 自定义XAxis
方法 | 作用 |
---|---|
setLabelRotationAngle(float angle) | 设置绘制x轴标签的角度(以度为单位) |
setPosition(XAxisPosition pos) | 设置XAxis位置。 在TOP,BOTTOM,BOTH_SIDED,TOP_INSIDE或BOTTOM_INSIDE之间进行选择 |
5.2 示例代码
XAxis xAxis = chart.getXAxis();
xAxis.setPosition(XAxisPosition.BOTTOM);
xAxis.setTextSize(10f);
xAxis.setTextColor(Color.RED);
xAxis.setDrawAxisLine(true);
xAxis.setDrawGridLines(false);
// set a custom value formatter
xAxis.setValueFormatter(new MyCustomFormatter());
// and more...
6. YAxis
YAxis是AxisBase的子类。 这个wiki只描述了YAxis,而不是父类。
YAxis类(在2.0.0版本的中称为YLabels),是与垂直轴相关的所有数据和信息容器。 每个Line-,Bar-,Scatter或CandleStickChart都有一个左和右YAxis对象,分别负责左轴或右轴。 RadarChart只有一个YAxis。 默认情况下,图表的两个轴都被启用,并将被绘制。
通过如下方式获取YAxis实例:
YAxis leftAxis = chart.getAxisLeft();
YAxis rightAxis = chart.getAxisRight();
YAxis leftAxis = chart.getAxis(AxisDependency.LEFT);
YAxis yAxis = radarChart.getYAxis(); // this method radarchart only
在运行时,使用public AxisDependency getAxisDependency()来确定此轴表示的图表的边。
所有会影响到轴数值范围的自定义设置都需要在设置图表数据之前完成。
6.1 Axis Dependency
根据默认值,添加到图表的所有数据都会与图表的左侧YAxis对应。 如果没有进一步指定和启用,则右侧的YAxis被调整为与左轴相同的刻度。
如果你的图表需要支持不同的轴刻度,则可以通过设置数据应该对应的轴来实现。 这可以通过更改DataSet对象的AxisDependency来实现:
LineDataSet dataSet = ...; // get a dataset
dataSet.setAxisDependency(AxisDependency.RIGHT);
设置此项将更改你的数据对应的轴。
6.2 零线
除了沿YAxis上的每个值水平位置的网格线之外,还有一个所谓的零线,它在轴上的零(0)值处绘制,并且与网格线相似,但可以单独配置。
方法 | 作用 |
---|---|
setDrawZeroLine(boolean enabled) | 启用 / 禁用 零线。 |
setZeroLineWidth(float width) | 设置零线的宽度。 |
setZeroLineColor(int color) | 设置零线的颜色 |
零线示例代码:
// data has AxisDependency.LEFT
YAxis left = mChart.getAxisLeft();
left.setDrawLabels(false); // no axis labels
left.setDrawAxisLine(false); // no axis line
left.setDrawGridLines(false); // no grid lines
left.setDrawZeroLine(true); // draw a zero line
mChart.getAxisRight().setEnabled(false); // no right axis
上述代码结果如下所示。 不绘制轴值,不绘制网格线或轴线,只绘制零线。
6.3 更多示例代码
YAxis yAxis = mChart.getAxisLeft();
yAxis.setTypeface(...); // set a different font
yAxis.setTextSize(12f); // set the text size
yAxis.setAxisMinimum(0f); // start at zero
yAxis.setAxisMaximum(100f); // the axis maximum is 100
yAxis.setTextColor(Color.BLACK);
yAxis.setValueFormatter(new MyValueFormatter());
yAxis.setGranularity(1f); // interval 1
yAxis.setLabelCount(6, true); // force 6 labels
//... and more
MPAndroidChart Wiki(译文)~Part 1的更多相关文章
- MPAndroidChart Wiki(译文)~Part 4
16. 动画 注意:本章的动画效果只会在API 11(Android3.0.x)及以上的Android版本上生效 在低于上述的Android版本中,动画将不会被执行,并不会导致程序崩溃. 所有类型的图 ...
- MPAndroidChart Wiki(译文)~Part 6
22. ViewPortHandler ViewPortHandler负责处理图表的视窗.也就是说它负责图表视图中的展示给用户的那部分内容.包括图表位移,缩放级别,图表大小和绘制区域以及当前偏移量.V ...
- MPAndroidChart Wiki(译文)~Part 5
19. ChartData子类 这篇wiki主要关注ChartData子类的具体介绍.至于此部分没有提及到的ChartData的子类,代表他们没有特性功能需要介绍. BarData 方法 使用 set ...
- MPAndroidChart Wiki(译文)~Part 2
7. 填充数据 这一章节将讲解给各式各样的图表设置数据的方法. 7.1 LineChart(线形图) 想给图表添加数据,使用如下方法: public void setData(ChartData da ...
- MPAndroidChart Wiki(译文)~Part 3
13. 图例 默认情况下,所有的图表都支持图例并且会自动生成.给图表设置完数据之后,图例会被绘制出来.图例通常由多个条目组成,每个条目由标签形式/形状表示. 自动生成的图例包含的条目数取决于不同颜色的 ...
- MPAndroidChart的具体属性方法
android中常用的第三方图表MPAndroidChart的一些具体属性及方法说明 注意:在将折线图转为曲线图时,lineDataSet.setMode(LineDataSet.Mode.CUBIC ...
- <Android 应用 之路> MPAndroidChart~BubbleChart(气泡图) and RadarChart(雷达图)
简介 MPAndroidChart是PhilJay大神给Android开发者带来的福利.MPAndroidChart是一个功能强大并且使用灵活的图表开源库,支持Android和iOS两种,这里我们暂时 ...
- <Android 应用 之路> MPAndroidChart~ScatterChart
简介 MPAndroidChart是PhilJay大神给Android开发者带来的福利.MPAndroidChart是一个功能强大并且使用灵活的图表开源库,支持Android和IOS两种,这里我们暂时 ...
- <Android 应用 之路> MPAndroidChart~PieChart
简介 MPAndroidChart是PhilJay大神给Android开发者带来的福利.MPAndroidChart是一个功能强大并且使用灵活的图表开源库,支持Android和IOS两种,这里我们暂时 ...
随机推荐
- 20145324 《Java程序设计》第6周学习总结
20145324 <Java程序设计>第6周学习总结 教材学习内容总结 第十章 1.使用输入串流将数据从来源取出 InputStream 使用输出串流将数据写入目的地 OutStream ...
- 20144303 《Java程序设计》第八周学习总结
20144303 <Java程序设计>第八周学习总结 教材学习内容总结 第十五章 1.日志API简介: java.util.logging包提供了日志功能相关类与接口,不必额外配置日志组件 ...
- 学习记录:交叉编译环境配置(buildroot and gdb&gdbserver)【转】
本文转载自:https://blog.csdn.net/zhy025907/article/details/52332528 1,背景 因为参加公司的路由器逆向培训,首先需要的就是环境的配置准备工作, ...
- Android Studio开发学习 - 1. 添加Activity
1. 项目上点右键,New -> Activity -> Blank Activity 这将生成Activity的 Layout.Class .和相关的配置信息(在AndroidManif ...
- Android -- ContentObserver 内容观察者
1. 实现原理图 2. 示例代码 (暂时有个问题,短信观察者 收到一条短信时 onchange方法会执行两次, 解决方法为:每次监听到变化的时候就去取最新短信的id,跟上次取的比较,如果一样的就不做处 ...
- 从源码角度分析 Kotlin by lazy 的实现
by lazy 的作用 延迟属性(lazy properties) 是 Kotlin 标准库中的标准委托之一,可以通过 by lazy 来实现. 其中,lazy() 是一个函数,可以接受一个 Lamb ...
- angular2.x 下拉多选框选择组件
angular2.x - 5.x 的下拉多选框选择组件 ng2 -- ng5.最近在学angular4,经常在交流群看见很多人问 下拉多选怎么做... 今天就随便写的个. 组件源码 百度云 链接: ...
- JS书籍推荐
JS书籍推荐 一.总结 一句话总结: 二.JS进阶书籍 第一阶段:<JavaScript DOM编程艺术> 看这本书之前,请先确认您对Javascript有个基本的了解,应该知道if el ...
- Spring自定义注解扫描的实现
目标:实现自定义spring自动扫描注解.主要为后期实现分布式服务框架自动注解提供技术支持 技术分析:通过配置组件扫描标签使spring解析标签. 1. JewelScanBeanDefaultPar ...
- 设计模式--组合模式C++实现
组合模式C++实现 1定义 将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性 2类图 角色分析 Component抽象构建角色 定义参加组合独享的共同方 ...