前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >设计模式(二):Android 源码中的工厂模式

设计模式(二):Android 源码中的工厂模式

作者头像
Frank909
发布2020-08-03 19:23:23
1K0
发布2020-08-03 19:23:23
举报
文章被收录于专栏:Frank909Frank909

之前的文章介绍了单例模式,单例模式非常简单,也很容易懂。本文介绍另外一种简单的创建型设计模式:工厂模式(Factory Pattern)。

什么是工厂模式?

工厂模式(Factory Pattern)在实际开发中非常常见,它可以由用户决定创建对象的类型。

因为工厂模式,我们无需向客户暴露我们的代码逻辑,只需要开放接口给客户,由客户指定要创建的对象的类型,便可以动态生成符合需求的类别对象。

什么场合用工厂模式?

需要根据实际情况才能决定创建何种类别对象的场景。

听起来挺悬乎的,其实很容易理解。

假设,你要从广州到深圳,你就需要交通工具。

选择可就多了,有大巴,有火车,有高铁,有动车,未来还有地铁和城轨。

你在不同时刻有不同的选择。

比较,你是土豪,你还可以坐飞机。

你不想转车,可能直接大巴。

你要便宜点,你可以坐火车。

干净舒适时,你可以选择高铁。

下面,实例讲解。

工厂模式的实现手段

交通工具可以是一个抽奖类,也可以是一个接口。

所以,我们定义一个接口代表交通工具,之后把大巴、火车、飞机实现这个接口,UML 图如下。

我们再编写工厂类。

在这里插入图片描述
在这里插入图片描述

我们通过 TransportationFactory 这个类中的 getTransportation() 方法就可以创建类了。

下面是 Java 代码示意:

Transportation.java

代码语言:javascript
复制
public interface Transportation {
   void move(String dst);
}

再实现 Bus、Train、Plane

Bus.java

代码语言:javascript
复制
public class  Bus  implements Transportation{

    @Override
    public void move(String dst) {
        // TODO Auto-generated method stub
        System.out.println("Take a bus to "+dst);
    }
}

Train.java

代码语言:javascript
复制
public class  Train  implements Transportation{

    @Override
    public void move(String dst) {
        // TODO Auto-generated method stub
        System.out.println("Take a train to "+dst);
    }
}

Plane.java

代码语言:javascript
复制
public class  Plane  implements Transportation{

    @Override
    public void move(String dst) {
        // TODO Auto-generated method stub
        System.out.println("Take a plane to "+dst);
    }
}

然后,我们实现工厂类

Transportation.java

代码语言:javascript
复制
public class TranportationFactory {

    public Transportation getTransportation(String type){
        if(type == null){
            return null;
        }        
        if(type.equalsIgnoreCase("TRAIN")){
            return new Train();
        } else if(type.equalsIgnoreCase("BUS")){
            return new Bus();
        } else if(type.equalsIgnoreCase("PLANE")){
            return new Plane();
        }
        return null;
    }
    
}

可以看到,工厂类根据 type 的不同,选择创建不同的类别对象。

最后,编写测试代码。 FactoryDemo.java

代码语言:javascript
复制
public class FactoryDemo {

    public static void main(String[] args) {

        TranportationFactory factory = new TranportationFactory();

        //Transportation transportation = factory.getTransportation("bus");
         Transportation transportation = factory.getTransportation("train");
        // Transportation transportation = factory.getTransportation("plane");

        transportation.move("深圳");
    }

}

最终,打印结果如下:

代码语言:javascript
复制
Take a train to 深圳

我们可以看到,通过简单的例子,我们掌握了工厂模式的基础方法,下面通过实际的源码例子加深理解。

Android 源码中的工厂模式

xref: /packages/apps/Camera2/src/com/android/camera/debug/Logger.java

代码语言:javascript
复制
public interface Logger {

    ......

    /**
     * Provides a Logger instance from a given Log tag.
     */
    public interface Factory {
        public Logger create(Tag tag);
    }
}

这是 Android 系统应用相机的一份代码,主要是记录 Log 的,但它是一个接口,说明这个应用中有不同的 Logger,并且里面还有一个接口 Factory,通过传入 Tag 可以生成不同的 Logger。

经查询 Logger 有 2 种实现类,TagLogger 和 NoOpLogger,它们的代码在 Loggers.java 中。

因为篇幅所限,这里只讨论 TagLogger。

xref: /packages/apps/Camera2/src/com/android/camera/debug/Loggers.java

代码语言:javascript
复制
public class Loggers {


    /**
     * This creates a factory that will use the standard android static log
     * methods.
     */
    public static Logger.Factory tagFactory() {
        return TagLoggerFactory.instance();
    }

    /**
     * Creates a logger factory which always returns the given logger.
     */
    public static Logger.Factory factoryFor(final Logger logger) {
        return new Logger.Factory() {
            @Override
            public Logger create(Tag tag) {
                return logger;
            }
        };
    }



    /**
     * Creates loggers that use tag objects to write to standard android log
     * output.
     */
    private static class TagLoggerFactory implements Logger.Factory {
        private static class Singleton {
            private static final TagLoggerFactory INSTANCE = new TagLoggerFactory();
        }

        public static TagLoggerFactory instance() {
            return Singleton.INSTANCE;
        }

        @Override
        public Logger create(Tag tag) {
            return new TagLogger(tag);
        }
    }

  
    /**
     * TagLogger logger writes to the standard static log output with the given
     * tag object.
     */
    private static class TagLogger implements Logger {
        private final Log.Tag mTag;

        public TagLogger(Log.Tag tag) {
            mTag = tag;
        }
        ...
    
    }
}

很惊喜的是,这个例子也可以用来解释单例模式。

TagLogger.Factory 中的 create 方法可以创建 TaggLogger。

所以,从入口方法 factoryFor()就可以决定不同的 Factory,不同的 Factory 就创建了不同的 Logger。

这显然是工厂模式。

总结

  1. 工厂模式非常简单,它符合里氏替换原则。
  2. 工厂模式的本质是将对象的类型确定延迟到子类,由子类自主决定。
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-08-02 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是工厂模式?
  • 什么场合用工厂模式?
  • 工厂模式的实现手段
  • Android 源码中的工厂模式
  • 总结
相关产品与服务
日志服务
日志服务(Cloud Log Service,CLS)是腾讯云提供的一站式日志服务平台,提供了从日志采集、日志存储到日志检索,图表分析、监控告警、日志投递等多项服务,协助用户通过日志来解决业务运维、服务监控、日志审计等场景问题。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档