迭代器模式实现与研究 - bei1999/work GitHub Wiki
定义
提供了一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。
场景模拟
迭代器模式又称为游标(cursor)模式,源自于容器类的访问,比如java 中的list ,map 数组等,将遍历的方法封装到容器中,方式容器类的内部细节暴露,因此产生了迭代器模式
实现
说到游标,首先想到的是android 中的数据库中的cursor,下面是通过ContentProvider 调用数据库操作例子来纵观整个过程:
/**
* author : lzb
* e-mail :
* time : 2017/12/20
* desc : 数据库管理类
* version: 1.0
*/
public class DBHelper extends SQLiteOpenHelper {
public DBHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, null, version);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE table_fav (_id INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT,age TEXT)");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS table_fav");
onCreate(db);
}
}
/**
* author : lzb
* e-mail :
* time : 2017/12/20
* desc : 对外提供数据接口类
* version: 1.0
*/
public class DataProvider extends ContentProvider {
private DBHelper mDBHelper;
private static final String DB_NAME = "favor.db";
private static final String DB_TABLE = "table_fav";
private static final int DB_VERSION = 1;
private SQLiteDatabase db;
@Override
public boolean onCreate() {
mDBHelper = new DBHelper(getContext(), DB_NAME, null, DB_VERSION);
db = mDBHelper.getWritableDatabase();
if (db == null) {
return false;
} else {
return true;
}
}
@Nullable
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
// SQLiteDatabase db = mDBHelper.getReadableDatabase();
return db.query(DB_TABLE, projection, null, null, null, null, null);
}
@Nullable
@Override
public String getType(@NonNull Uri uri) {
return null;
}
@Nullable
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
long id = db.insert(DB_TABLE,null,values);
if (id > 0) {
Uri newUri = ContentUris.withAppendedId(Favor.CONTENT_URI,id);
getContext().getContentResolver().notifyChange(newUri,null);
return newUri;
}
throw new SQLException("failed to insert row into" +uri);
}
@Override
public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
return 0;
}
@Override
public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
return 0;
}
}
/**
* author : lzb
* e-mail :
* time : 2017/12/21
* desc : 常量
* version: 1.0
*/
public class Favor {
public static final String AUTHORITY = "com.bei.test.db.DataProvider";
public static final String PATH = "table_fav";
public static final String CONTENT_URL_STRING = "content://" +AUTHORITY +"/"+PATH;
public static final Uri CONTENT_URI = Uri.parse(CONTENT_URL_STRING);
public static final String KEY_NAME = "name";
public static final String KEY_AGE = "age";
}
/**
* author : lzb
* e-mail : [email protected]
* time : 2017/12/20
* desc : 测试类
* version: 1.0
*/
public class ContentResolverDemoActivity extends Activity {
private static final String[] PROJECTION = new String[]{"name", "age"};
@Bind(R.id.nameTv)
EditText nameTv;
@Bind(R.id.ageTv)
EditText ageTv;
@Bind(R.id.addBtn)
Button addBtn;
@Bind(R.id.queryBtn)
Button queryBtn;
@Bind(R.id.resultTv)
TextView resultTv;
@Bind(R.id.resultUrl)
TextView resultUrl;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main09);
ButterKnife.bind(this);
}
@OnClick({R.id.addBtn, R.id.queryBtn})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.addBtn:
ContentValues contentValues = new ContentValues();
contentValues.put(Favor.KEY_NAME, nameTv.getText().toString());
contentValues.put(Favor.KEY_AGE, ageTv.getText().toString());
Uri newUrl = this.getContentResolver().insert(Favor.CONTENT_URI, contentValues);
resultUrl.setText("添加成功 ,URI:" + newUrl);
break;
case R.id.queryBtn:
Cursor cursor = getContentResolver().query(Favor.CONTENT_URI, PROJECTION, null, null, null);
String msg = "";
cursor.moveToFirst();
do {
msg += "name: " + cursor.getString(0);
msg += "age: " + cursor.getString(1)+"\n";
} while (cursor.moveToNext());
cursor.close();
resultTv.setText(msg);
break;
}
}
}
使用ContentProvider的时候,不要忘记AndroidManifest.xml中注册声明
<provider
android:authorities="com.bei.test.db.DataProvider"
android:name=".db.DataProvider"/>
运行结果如下:
分析
使用了SQLiteOpenHelper 的query 方法查询,最终返回一个cursor 的游标对象,这其实就是一个迭代器,通过遍历游标的位置进行数据的遍历和查询。
总结
它的存在弱化了容器类与遍历算法之前的关系,很多语言比如java python等自身实现了迭代器功能,对于开发者而言很少自己去实现迭代器。