王学岗简单工厂模式和工厂方法模式

本文通过集成不同地图引擎的例子,介绍了简单工厂模式和工厂方法模式的应用。从代码耦合问题出发,逐步展示如何通过工厂模式降低系统耦合度,并探讨在面对多样化的地图功能时,如何进一步优化工厂设计。

我们举工作中的一个例子,老板让我集成百度地图,我完成工作了,可是老板又改注意了,让我集成高德地图,这时候怎么办,要是以前我直接拿板砖去招呼老板了!
假如我们已经实现了百度地图的集成

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);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值