在软件开发中,有时也会遇到类似的情况,某个方法的实现需要多个步骤(类似“请客”),其 中有些步骤是固定的(类似“点单”和“买单”),而有些步骤并不固定,存在可变性(类似“吃 东西”)。为了提高代码的复用性和系统的灵活性,可以使用一种称之为模板方法模式的设计 模式来对这类情况进行设计,在模板方法模式中,将实现功能的每一个步骤所对应的方法称 为基本方法(例如“点单”、“吃东西”和“买单”),而调用这些基本方法同时定义基本方法的执 行次序的方法称为模板方法(例如“请客”)。在模板方法模式中,可以将相同的代码放在父类 中,例如将模板方法“请客”以及基本方法“点单”和“买单”的实现放在父类中,而对于基本方 法“吃东西”,在父类中只做一个声明,将其具体实现放在不同的子类中,在一个子类中提 供“吃面条”的实现,而另一个子类提供“吃满汉全席”的实现。通过使用模板方法模式,一方面 提高了代码的复用性,另一方面还可以利用面向对象的多态性,在运行时选择一种具体子 类,实现完整的“请客”方法,提高系统的灵活性和可扩展性。 模板方法模式定义如下: 模板方法模式:定义一个操作中算法的框架,而将一些步骤延迟到子类中。模板方法模 式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 Template Method Pattern: Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.
模板方法模式是一种基于继承的代码复用技术,它是一种类行为型模式。 模板方法模式是结构最简单的行为型设计模式,在其结构中只存在父类与子类之间的继承关 系。通过使用模板方法模式,可以将一些复杂流程的实现步骤封装在一系列基本方法中,在 抽象父类中提供一个称之为模板方法的方法来定义这些基本方法的执行次序,而通过其子类 来覆盖某些步骤,从而使得相同的算法框架可以有不同的执行结果。模板方法模式提供了一 个模板方法来定义算法框架,而某些具体步骤的实现可以在其子类中完成。
数据查询表多个情况下,存在很多冗余代码。getCapk函数的代码。getAid函数的代码query函数的代码都有点重复,但是又不完全相同。但是冗余代码太多了又什么好的设计模式能处理好这个情况?
public List<EMV_CAPK> getCapk(int acquirerIdx) {SQLiteDatabase db = emvDbHelper.getReadableDatabase();List<EMV_CAPK> capkList = new ArrayList<>();String[] columns = {EmvDbHelper.rid,EmvDbHelper.capkIndex,EmvDbHelper.keyExp,EmvDbHelper.keyMod,EmvDbHelper.checksum};String selection = EmvDbHelper.acquirerId + " = ?";String[] selectionArgs = {String.valueOf(acquirerIdx)};Cursor cursor = db.query(EmvDbHelper.TABLE_CAPK,columns,selection,selectionArgs,null,null,null);while (cursor.moveToNext()) {EMV_CAPK emvCapk = createEMVCapkFromCursor(cursor);capkList.add(emvCapk);}cursor.close();db.close();return capkList;}
public String query(int acquirerIdx) {String version = null;SQLiteDatabase db = emvDbHelper.getReadableDatabase();// 定义要查询的列String[] columns = {EmvDbHelper.tableVersion};// 设置查询条件String selection = EmvDbHelper.acquirerId + " = ?";String[] selectionArgs = {String.valueOf(acquirerIdx)};Cursor cursor = db.query(EmvDbHelper.TABLE_ACQUIRER,columns,selection,selectionArgs,null,null,null);if (cursor.moveToFirst()) {// 尝试获取 tableVersion 列的索引int tableVersionIndex = cursor.getColumnIndex(EmvDbHelper.tableVersion);// 检查索引是否有效if (tableVersionIndex >= 0) {// 列存在,可以安全地访问version = cursor.getString(tableVersionIndex);}}cursor.close();db.close();return version;}
改良后的代码。
public abstract class DatabaseQueryTemplate {protected EmvDbHelper emvDbHelper;protected String tableName;public DatabaseQueryTemplate(EmvDbHelper emvDbHelper) {this.emvDbHelper = emvDbHelper;}public DatabaseQueryTemplate(EmvDbHelper emvDbHelper, String tableName) {this.emvDbHelper = emvDbHelper;this.tableName = tableName;}public Map<String, Object> executeQuery(String[] columnsToSelect, String selectionColumn, String selectionValue) {SQLiteDatabase db = emvDbHelper.getReadableDatabase();Cursor cursor = db.query(tableName,columnsToSelect,selectionColumn + " = ?",new String[]{selectionValue},null,null,null);Map<String, Object> result = new HashMap<>();if (cursor.moveToFirst()) {result = DatabaseUtil.getColumnValues(cursor, columnsToSelect);}cursor.close();db.close();return result;}protected abstract void processRow(Cursor cursor);
}
public class AidQuery extends DatabaseQueryTemplate {private List<Tables.AidTable> result;public AidQuery(EmvDbHelper emvDbHelper) {super(emvDbHelper, EmvDbHelper.TABLE_AID);result = new ArrayList<>();}public List<Tables.AidTable> getResult() {return result;}@Overrideprotected void processRow(Cursor cursor) {}
}
public String getAcqIndexList(String aid){AidQuery aidQuery = new AidQuery(emvDbHelper);String[] columnsToSelect = {EmvDbHelper.acquirerId,EmvDbHelper.aidIndex};String selectionColumn = EmvDbHelper.aid;String selectionValue = aid;Map<String, Object> result = aidQuery.executeQuery(columnsToSelect, selectionColumn, selectionValue);// 在这里可以根据需要处理 result,例如将其转换为字符串返回// 以下代码是示例,具体处理逻辑根据实际需求修改StringBuilder resultString = new StringBuilder();for (String columnName : columnsToSelect) {Object columnValue = result.get(columnName);if (columnValue != null) {resultString.append(columnValue);}}return resultString.toString();}
String acqIndexList = dbManager.getAcqIndexList(aid);Logs.d(TAG,"acqIndexList= "+ acqIndexList);