@Tyhj
        
        2019-01-31T07:20:57.000000Z
        字数 4092
        阅读 994
    设计模式
策略模式定义了一系列的算法,并将每个算法封装起来,而且使它们还可以相互替换。
- 针对同一种问题的多种处理方式,仅仅是具体行为有差别时
 - 需要安全地封装同一种类型的操作的时候
 - 出现同一抽象类有多个子类,而又需要使用if-else 或者 swith-case来选择具体子类时
 
其实就是当有多种策略来解决问题的时候,我们封装每一种方法,然后让它可以相互替换,这样增强程序的可拓展性、可维护性;
实现方法其实一般就是抽象出策略接口来,每一种具体的策略去实现接口,这样封装了每个策略;实现了同一个接口,所以可以相互替换

这个模式其实非常常见,比如图片加载框架中,图片可以被缓存在内存中、缓存在本地文件中、保存到服务器;那么获取图片的时候,也可以从缓存中找,从本地文件找,从服务器取;开闭原则这篇文章里面已经讲过了,这其实就是一个策略模式的例子
重新举一个例子,微信跳一跳在2017年年末的时候很火,跳一跳外挂也很火,之前也根据颜色识别写了Android上实现微信跳一跳外挂;其中最主要的就是颜色识别,计算两种颜色的相似度,算法大概试了三种;
首先抽象出颜色相似的接口
public interface LikeColor {/*** 两种颜色是否相似** @param color1* @param color2* @param aberration 允许差异值* @return*/boolean isLike(int color1, int color2, double aberration);}
实现HSV颜色空间算法
public class HsvColorLike implements LikeColor {@Overridepublic boolean isLike(int color1, int color2, double aberration) {if (hsvAberration(color1, color2) <= aberration) {return true;}return false;}/*** HSV颜色空间计算颜色距离*/public static double hsvAberration(int color1, int color2) {float[] tempHSV1 = new float[3];Color.colorToHSV(color1, tempHSV1);float[] tempHSV2 = new float[3];Color.colorToHSV(color2, tempHSV2);HSV hsv1 = new HSV();hsv1.H = tempHSV1[0];hsv1.S = tempHSV1[1];hsv1.V = tempHSV1[2];HSV hsv2 = new HSV();hsv2.H = tempHSV2[0];hsv2.S = tempHSV2[1];hsv2.V = tempHSV2[2];return HSV.distanceOf(hsv1, hsv2);}public static class HSV {public float H;public float S;public float V;//self-definedprivate static final double R = 100;private static final double angle = 30;private static final double h = R * Math.cos(angle / 180 * Math.PI);private static final double r = R * Math.sin(angle / 180 * Math.PI);/*** HSV颜色空间计算颜色距离* HSV是个六棱锥模型,这个模型中颜色的参数分别是:色调(H),饱和度(S),明度(V)** @param hsv1* @param hsv2* @return*/public static double distanceOf(HSV hsv1, HSV hsv2) {double x1 = r * hsv1.V * hsv1.S * Math.cos(hsv1.H / 180 * Math.PI);double y1 = r * hsv1.V * hsv1.S * Math.sin(hsv1.H / 180 * Math.PI);double z1 = h * (1 - hsv1.V);double x2 = r * hsv2.V * hsv2.S * Math.cos(hsv2.H / 180 * Math.PI);double y2 = r * hsv2.V * hsv2.S * Math.sin(hsv2.H / 180 * Math.PI);double z2 = h * (1 - hsv2.V);double dx = x1 - x2;double dy = y1 - y2;double dz = z1 - z2;return Math.sqrt(dx * dx + dy * dy + dz * dz);}}}
实现LAB颜色空间算法
public class LabColorLike implements LikeColor {@Overridepublic boolean isLike(int color1, int color2, double aberration) {if (labAberration(color1, color2) <= aberration) {return true;}return false;}/*** LAB颜色空间计算色差,基于人眼对颜色的感知,* 可以表示人眼所能感受到的所有颜色。* L表示明度,A表示红绿色差,B表示蓝黄色差*/public static int labAberration(int color1, int color2) {int r1 = Color.red(color1); // 取高两位int g1 = Color.green(color1);// 取中两位int b1 = Color.blue(color1);// 取低两位int r2 = Color.red(color2); // 取高两位int g2 = Color.green(color2);// 取中两位int b2 = Color.blue(color2);// 取低两位int rmean = (r1 + r2) / 2;int r = r1 - r2;int g = g1 - g2;int b = b1 - b2;return (int) Math.sqrt((2 + rmean / 256) * (Math.pow(r, 2)) + 4 * (Math.pow(g, 2)) + (2 + (255 - rmean) / 256) * (Math.pow(b, 2)));}}
最后自己也写了一个基于RGB的简单的颜色算法
public class RgbColorLike implements LikeColor {@Overridepublic boolean isLike(int color1, int color2, double aberration) {return baseLike(color1, color2, aberration);}/*** @param color1 第一种颜色* @param color2 第二种颜色* @return*/public boolean baseLike(int color1, int color2, double aberration) {int red = Color.red(color1); // 取高两位int green = Color.green(color1);// 取中两位int blue = Color.blue(color1);// 取低两位int red2 = Color.red(color2); // 取高两位int green2 = Color.green(color2);// 取中两位int blue2 = Color.blue(color2);// 取低两位if (red == red2 && green == green2 && blue == blue2) {return true;}if ((Math.abs(red - red2) < aberration && Math.abs(green - green2) < aberration && Math.abs(blue - blue2) < aberration) &&(Math.abs(red - red2) + Math.abs(green - green2) + Math.abs(blue - blue2)) < aberration * 2.5) {return true;}return false;}/*** 简单的RGB颜色判断** @return*/public static void rgbAberration(int color1, int color2) {int red1 = Color.red(color1); // 取高两位int green1 = Color.green(color1);// 取中两位int blue1 = Color.blue(color1);// 取低两位int red2 = Color.red(color2); // 取高两位int green2 = Color.green(color2);// 取中两位int blue2 = Color.blue(color2);// 取低两位int red = Math.abs(red1 - red2);int green = Math.abs(green1 - green2);int blue = Math.abs(blue1 - blue2);LogUtils.e("RGB颜色判断:色差:" + red + "," + green + "," + blue + ",all:" + (red + green + blue));}}
对比颜色的时候就可以随意调用任意一种算法
/*** 对比颜色** @param color1* @param color2* @param aberration* @return*/public static boolean colorLike(int color1, int color2, int aberration, LikeColor labLike) {return labLike.isLike(color1, color2, aberration);}
理解起来很简单,平时应该也会频繁用到,遵循单一职责原则和开闭原则,增强了程序的可拓展性,可维护性。