一、装饰模式
动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
装饰模式的出现
用例子说明:我们想要表达一个人,穿不同衣服,体现不同个性的一个程序。
首先定义一个人Person类;在定义一个抽象的衣服Clothes类,然后有各种衣服的子类。
在客户端通过实例化“人”,然后再实例化需要的“衣服”,分别调用show 方法。
这样也可以达到目的,但是我们看分析一下客户端。
Person a=new Person("小明"); T恤 t=new T恤(); 垮裤 K=new 垮裤(); 球鞋 q=new 球鞋(); //显示 a.show(); t.show(); k.show(); q.show();
问题一:从上述代码中可以看出这些穿衣服的顺序我们可以任意调换,但是一调换,是不是,可能就是另外一种装扮了,所以这样写的代码结构不稳定。
问题二:以上是一种装扮,如果我要展示N中装扮呢,我就需要把这些代码重复N遍。
为了避免这些问题,所以有了装饰模式。
使用装饰模式可以再客户端中将装饰过程进行嵌套封装,即使同样的衣服,改变一下顺序,就可以穿出两种风格。而且,穿衣服的件数不一定相同。
同时还减少了代码的数量,只需要用一个show 方法就可以调出嵌套的一系列动作。
使用装饰模式:
需要再衣服类中增加一个Decorate 方法,用来给嵌套的要装饰对象赋值。
代码显示:
Person a=new Person("小明"); T恤 t=new T恤(); 垮裤 K=new 垮裤(); 球鞋 q=new 球鞋(); //动作嵌套 q.decorate(a); k.decorate(q); t.decorate(k); //显示 t.show();
二、类图
我们都知道做程序员有时会恶搞,就像android中,程序员在setting中就隐藏这样一个功能:
我们可以找到“关于手机"这一项在里面有“android版本”这一项,如图:
当我们快速点击“android版本”这一项时会弹出一张图片(恶搞型,这是2.3操作
系统,但是4.0系统的话会弹出一个android标志图片
,你按住android标志不放的话会出现很多android标志在移动的动画:
)。
这里我们就说说2.3系统的:
首先我们找到Settings的源码,在package/app/Settings/src/com/android/settings下,我们要找到
DeviceInfoSettings.java这个文件,就是“关于手机”这一项的相关代码,在其的OnCreate方法中引用了一个xml文件:
(R.xml.device_info_settings);
所以我们找到device_info_settings.xml文件看看:
<!-- Device firmware version --> <Preference android:key="firmware_version" style="?android:preferenceInformationStyle" android:title="@string/firmware_version" android:summary="@string/device_info_default"/>
这个就是代表“android版本”的相关代码,我们可以看到它的Key是
firmware_version
所以我们在java文件中就去找到它所被引用的代码,在DeviceInfoSettings.java中有一个 public boolean onPreferenceTreeClick方法:
@Override public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { if (preference.getKey().equals("firmware_version")) { System.arraycopy(mHits, 1, mHits, 0, mHits.length-1); mHits[mHits.length-1] = SystemClock.uptimeMillis(); if (mHits[0] >= (SystemClock.uptimeMillis()-500)) { Intent intent = new Intent(Intent.ACTION_MAIN); intent.setClassName("android", com.android.internal.app.PlatLogoActivity.class.getName()); try { startActivity(intent); } catch (Exception e) { } } } return super.onPreferenceTreeClick(preferenceScreen, preference); }
在其中就实现了你快速点击“android版本”这一项所实现的功能。
解决方案整理自CSDN问答:http://ask.csdn.net/questions/703
Location对象带和距离相关的方法,求两个坐标距离: public static void distanceBetween (double startLatitude, double startLongitude, double endLatitude, double endLongitude, float[] results)
Parameters startLatitude the starting latitude startLongitude the starting longitude endLatitude the ending latitude endLongitude the ending longitude results an array of floats to hold the results
详细解释见这里: distanceBetween(double, double, double, double, float[])
在大量坐标之间找最近距离的坐标如果你用Mongodb,获取最近的坐标很简单,Mongodb自带geoNearCommand,可以参照这里:GeospatialIndexing-geoNearCommand
> db.runCommand( { geoNear : "places" , near : [50,50], num : 10 } ); > db.runCommand({geoNear:"asdf", near:[50,50]}) { "ns" : "test.places", "near" : "1100110000001111110000001111110000001111110000001111", "results" : [ { "dis" : 69.29646421910687, "obj" : { "_id" : ObjectId("4b8bd6b93b83c574d8760280"), "y" : [ 1, 1 ], "category" : "Coffee" } }, { "dis" : 69.29646421910687, "obj" : { "_id" : ObjectId("4b8bd6b03b83c574d876027f"), "y" : [ 1, 1 ] } } ], "stats" : { "time" : 0, "btreelocs" : 1, "btreelocs" : 1, "nscanned" : 2, "nscanned" : 2, "objectsLoaded" : 2, "objectsLoaded" : 2, "avgDistance" : 69.29646421910687 }, "ok" : 1 }
PS. 这里有很多计算GEO距离相关的公式:http://www.movable-type.co.uk/scripts/latlong.html