我们举工作中的一个例子,老板让我集成百度地图,我完成工作了,可是老板又改注意了,让我集成高德地图,这时候怎么办,要是以前我直接拿板砖去招呼老板了!
假如我们已经实现了百度地图的集成
package com.example.acer.factorypattern;
import android.view.View;
/**
* @author w_x_g
* @time 2017/1/8 10:28
* @note ${TODO}
*/
public class BaiduMapView {
enum MapType{
//空白背景模式
MAP_TYPE_NONE,
//普通地图模式常量
MAP_TYPE_NORMAL,
//卫星图模式常量
MAP_TYPE_SATELLITE
}
public View getView(){
System.out.println("获取百度地图的MapView");
return null;
}
public void setMapType(MapType mapType){
System.out.println("设置了地图类型");
}
}
main方法
package com.example.acer.factorypattern;
/**
* @author w_x_g
* @time 2017/1/8 10:35
* @note ${TODO}
*/
public class MainTest {
public static void main(String args[]){
BaiduMapView baiduMapView=new BaiduMapView();
//获取百度地图的视图
baiduMapView.getView();
}
}
现在老板要我们集成高德地图,我们又按照要求集成了高德地图
package com.example.acer.factorypattern;
import android.view.View;
/**
* @author w_x_g
* @time 2017/1/8 10:28
* @note ${TODO}
*/
public class GaodeMapView {
enum MapType{
//空白背景模式
MAP_TYPE_NONE,
//普通地图模式常量
MAP_TYPE_NORMAL,
//卫星图模式常量
MAP_TYPE_SATELLITE
}
public View getView(){
System.out.println("获取高德地图的MapView");
return null;
}
public void setMapType(MapType mapType){
System.out.println("设置了地图类型");
}
}
//修改客户端
package com.example.acer.factorypattern;
/**
* @author w_x_g
* @time 2017/1/8 10:35
* @note ${TODO}
*/
public class MainTest {
public static void main(String args[]){
// BaiduMapView baiduMapView=new BaiduMapView();
// //获取百度地图的视图
// baiduMapView.getView();
GaodeMapView gaodeMapView=new GaodeMapView();
gaodeMapView.getView();
}
}
这时候我们发现,客户端与百度地图类耦合度非常的高,我们需要重写客户端的代码;非常之麻烦啊!
我们可以使用工厂模式来解决,本文先讲解下简单工厂模式
我们写一个接口,定义了地图的规范
package com.example.acer.factorypattern;
import android.view.View;
/**
* 定义了地图的规范
*/
public interface IMap {
enum MapType{
//空白背景模式
MAP_TYPE_NONE,
//普通地图模式常量
MAP_TYPE_NORMAL,
//卫星图模式常量
MAP_TYPE_SATELLITE
}
public View getView();
public void setMapType(MapType mapType);
}
高德地图与百度地图类,实现了Imap接口
package com.example.acer.factorypattern;
import android.view.View;
/**
* @author w_x_g
* @time 2017/1/8 10:28
* @note ${TODO}
*/
public class BaiduMapView implements IMap{
@Override
public View getView() {
System.out.println("调用了百度地图的getView");
return null;
}
@Override
public void setMapType(MapType mapType) {
System.out.println("调用了百度地图的setMapType");
}
}
package com.example.acer.factorypattern;
import android.view.View;
/**
* @author w_x_g
* @time 2017/1/8 10:28
* @note ${TODO}
*/
public class GaodeMapView implements IMap{
public View getView(){
System.out.println("调用高德地图的getView");
return null;
}
public void setMapType(MapType mapType){
System.out.println("调用了高德地图的setMapType");
}
}
工厂类我们加入了单例模式
package com.example.acer.factorypattern;
/**
* @author w_x_g
* @time 2017/1/8 11:29
* @note ${TODO}
*/
public class MapViewFactory {
enum MapType{
Baidu,Gaode;
}
private static MapViewFactory mMapViewFactory;
private MapViewFactory() {
}
public static MapViewFactory getInstance() {
if (mMapViewFactory == null) {
mMapViewFactory = new MapViewFactory();
}
return mMapViewFactory;
}
public IMap getMapView(MapType mapType){
IMap iMap=null;
switch (mapType){
case Gaode:
iMap=new GaodeMapView();
break;
case Baidu:
iMap=new BaiduMapView();
break;
}
return iMap;
}
}
我们在看下客户端
package com.example.acer.factorypattern;
/**
拿到MapView的实例,不需要考虑细节
降低了地图与客户端的耦合度
不在需要new BaiduMap();
*/
public class MainTest {
public static void main(String args[]){
IMap iMap = MapViewFactory.getInstance().getMapView(MapViewFactory.MapType.Baidu);
iMap.getView();
iMap.setMapType(IMap.MapType.MAP_TYPE_NONE);
}
}
在android中BitmapFactory,XmlPullParserFactory,CertificateFactory就是使用了简单工厂模式
简单工厂的总结:静态实例化符合我们要求的实例,核心是降低耦合
下面有这样的一种需求,百度地图新增了一项功能,但是高德地图没有该功能,这个时候IMap修改起来就很麻烦了,另外在IMap类里有很多判断,以后在增加搜狗地图还要增加判断分支;这个工厂类是公共的工厂,不能满足我们的需求。这样我们就引出了我们的工厂方法模式;
把工厂写成接口模式,针对不同的引擎创建不同的工厂
首先看下BaiduMapView和GaodeMapView类以及IMap接口
package com.example.acer.factorypattern;
import android.view.View;
/**
* 定义了地图的规范
*/
public interface IMap {
enum MapType{
//空白背景模式
MAP_TYPE_NONE,
//普通地图模式常量
MAP_TYPE_NORMAL,
//卫星图模式常量
MAP_TYPE_SATELLITE
}
public View getView();
public void setMapType(MapType mapType);
}
package com.example.acer.factorypattern;
import android.view.View;
/**
* @author w_x_g
* @time 2017/1/8 10:28
* @note ${TODO}
*/
public class BaiduMapView implements IMap{
@Override
public View getView() {
System.out.println("调用了百度地图的getView");
return null;
}
@Override
public void setMapType(MapType mapType) {
System.out.println("调用了百度地图的setMapType");
}
}
package com.example.acer.factorypattern;
import android.view.View;
/**
* @author w_x_g
* @time 2017/1/8 10:28
* @note ${TODO}
*/
public class GaodeMapView implements IMap{
public View getView(){
System.out.println("调用高德地图的getView");
return null;
}
public void setMapType(MapType mapType){
System.out.println("调用了高德地图的setMapType");
}
}
一个工厂类接口和两个具体的工厂类
package com.example.acer.factorypattern;
/**
* 把工厂写成接口模式
*/
public interface IMapFactory {
IMap getMapView();
}
package com.example.acer.factorypattern;
/**
* @author w_x_g
* @time 2017/1/8 14:38
* @note ${TODO}
*/
public class BaiduMapFactory implements IMapFactory {
@Override
public IMap getMapView() {
return new BaiduMapView();
}
}
package com.example.acer.factorypattern;
/**
* @author w_x_g
* @time 2017/1/8 14:41
* @note ${TODO}
*/
public class GaodeMapFactory implements IMapFactory {
@Override
public IMap getMapView() {
return new GaodeMapView();
}
}
main方法
package com.example.acer.factorypattern;
/**
* 方法工厂模式,Baidu的工厂与Gaode的工厂分开了,但又同时满足了工厂类的接口
* 百度天地图可以有自己的特殊模块,其他的地图有其它地图的特殊模块
*/
public class MainTest {
public static void main(String args[]){
IMapFactory iMapFactory=new BaiduMapFactory();
BaiduMapView baiduMapView= (BaiduMapView) iMapFactory.getMapView();
baiduMapView.getView();
baiduMapView.setMapType(IMap.MapType.MAP_TYPE_NONE);
}
}