一 什么是策略模式
设计模式是人们在解决软件开发过程中总结出来的智慧结晶。策略模式也是一种解决实际问题的技巧。
在讲策略模式之前,我们先来研究一下三国时期 一个励志小军阀的故事。
公元2世纪,你来到了三国乱世,作为一名割据了一个县城的初级军阀,正面对着与隔壁军阀老王的一场艰难决战。
双方的作战人数都达到了上千人,而你作为军事首领,十分紧张的策划着战争的各个细节:
粮草供应、情报收集、敌人策反,军心士气、作战方略等。
战场局势,瞬息万变,而你必须小心而严谨地操作这一切。
在另外一个平行时空内。
另外一个二十一世纪的你,作为一个初级的Android程序员,今天的工作内容是去绘制一幅五分钟K线图。这个功能模块的需求是:通过获取到的股票数据,将其按照规则绘制到UI组件上。
包括:
以蜡烛线的形式绘制出每五分钟的 股票涨跌情况,开盘价,收盘价、
以柔和曲线的方式绘制出M5-M10数据、
支持用户手动缩放,动态计算时间单元。
根据当前选择区域,动态绘制坐标轴等功能
具体效果参考这个。https://github.com/zmobs/DoChart
好,老天眷顾。
你在与老王的战争中大获全胜。现在你成为了统治了一个州的中等军阀,具体参考 孙坚,公孙瓒
此时的你已经是三国有头有脸的人物了,自然不能事必躬亲。但是军事事务却更加繁忙了。甚至可能同时要面对好几场战争。
比如孙坚,他虽然不在前线亲自作战,但是为了自己的身家性命和荣华富贵。他在每天的作战会议上都会对手下坐镇各地的四员大将 :程普,黄盖,韩当,祖茂 严加叮嘱:
首先要高举xxx理论,xxx思想,坚持听xx指挥 等重要问题。
其次
要做好粮草供应、情报收集、敌人策反,军心士气、作战方略等工作。
而另外一个平行空间内的你,因为任务完成的很好,现在要开始完全负责股票行情K线部分的绘制工作了。
炒股,或者了解股票业务的同学都知道,K线的业务主要包括这么几个方面。
分时图,分钟K线图,五日K线图,月K线图
效果类似:
虽然各自的展示和计算方式存在差异,但是其中最核心的部分依然很类似:
以蜡烛线的形式绘制出每五分钟的 股票涨跌情况,开盘价,收盘价、
以柔和曲线的方式绘制出M5-M10数据、
支持用户手动缩放,动态计算时间单元。
根据当前选择区域,动态绘制坐标轴等功能
好。上天再一次眷顾了你。
你打败了周边的其他军阀,成功的割据一方,改朝换代。三分天下。
首先,恭喜你做了皇帝,但是战争依然存在,居安思危实在是这个乱世中生存下去的重要原则。
作为最高领导,你依然叮嘱和监督着手下,以及手下的手下做好:
粮草供应、情报收集、敌人策反,军心士气、作战方略等。
这样才能去自信应对每一场战争。
而已经成为高级程序员的你,要完成股票行情部分的整体功能。
不仅仅包括K线的绘制,还包括各种通用的证券指标甚至很多自定义指标。 比如 MACD,VOL指标。 这些都要有各自的特定的展现方式:
VOL 要讲成交量以柱状图的形式展示。
MACD 需要以曲线展示EMA12,以上下对称变色块展示DEA
等等等等 无穷无尽。
效果参考
https://github.com/zmobs/DoChart
这要是每个实现都以一个组件的形式实现,不仅自己累死了。而且代码也大大的耦合在了一起。后续是没法维护了。
但是机智如你,成功的发现这些需求之间还是有共性可循的:
1 业务图形绘制
2 手势点击识别
3 坐标区域选定及动态更新。
于是策略模式营运而生。
二 策略模式有什么好处。
省心,省心,省心。 还是省心。
策略模式更多是系统解构上的优化,并非运行效率上的提升。
做皇帝的你,不需要费心了解手下的上百位将领的方方面面,我不管你长的丑不丑,也不关心你人品好不好。
我只关心你能否做到以上几点,把战争打赢。
作为程序员的你,讲一个复杂的模块,进行了块状切分。
本来要写十几次的界面组件通过拆分功能,实现了良好的扩展性和解耦合效果。
今后就算要实现其他什么乱七八糟的指标都可以通过集成策略接口,完美的扩展。
三 策略模式的使用场景:
策略模式:定义一系列的算法,把每一个算法封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。也称为政策模式(Policy)。(Definea family of algorithms,encapsulate each one, andmake them interchangeable. Strategy lets the algorithmvary independently from clients that use it. )
上面这段是摘自google的一段策略模式解释。 用人话来说就是:应用场景不固定的情况下,核心算法及处理逻辑可以进行封装。从而实现清晰,良好的代码。(个人理解)
代码示例:
这里仅给出 指标策略的接口代码,具体请参考github DoChart项目。
重点是 StockIndexView类
package com.dqqdo.dochart.ui.view.index;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.RectF;
import com.dqqdo.dochart.ui.view.stock.CandleBean;
import java.util.ArrayList;
import java.util.List;
/**
* 作者:duqingquan
* 时间:2017/7/21 17:04
*/
public abstract class IndexStrategy {
// 数据集合
ArrayList<CandleBean> candles;
/**
* 设置集合数据
* @param data 数据集合
*/
public void setData(ArrayList<CandleBean> data){
this.candles = data;
}
/**
* 获取数据集合
* @return 数据集合
*/
public ArrayList<CandleBean> getData(){
return candles;
}
/**
* 计算公式关键点
* @return
*/
abstract boolean calcFormulaPoint(int startIndex, int endIndex, RectF viewPort);
/**
* 获取Y轴描述字符串
* @return 字符串描述数组
*/
abstract String[] getDescYStr();
/**
* 获取x轴描述文本
* @return 文本数字
*/
abstract String[] getDescXStr();
/**
* 获取x轴描述文本对应坐标
* @return x坐标数组
*/
abstract Float[] getDescX();
/**
* 绘制指标数据
* @param canvas 画板
* @param paint 画笔
*/
abstract void drawIndex(Canvas canvas, Paint paint);
/**
* 获取指标名称
* @return 指标名称
*/
abstract String getIndexName();
/**
* 获取指标公式
* @return 指标公式
*/
abstract String getIndexFormula();
/**
* 获取选中的指标
* @return
*/
abstract int getSelectIndex(PointF pointF);
abstract void drawSelectIndex(Canvas canvas, Paint paint, int index);
}