前言

简略工厂在我的项目中使用的十分多,如果你使用切当,能够晋升我的项目的可浏览性。

工厂模式的定义

定义一个创立产品对象的工厂接口,将产品对象的理论创立工作推延到具体子工厂类当中。这满足创立型模式中所要求的“创立与应用相拆散”的特点。

简略工厂

如果要创立的产品不多,只有一个工厂类就能够实现,这种模式叫“简略工厂模式”。

简略工厂通常为静态方法,因而又叫动态工厂办法模式

长处:

  • 工厂类蕴含必要的逻辑判断,能够决定在什么时候创立哪一个产品的实例。客户端能够罢黜间接创立产品对象的职责,很不便的创立出相应的产品。工厂和产品的职责辨别明确。
  • 客户端无需晓得所创立具体产品的类名,只需晓得参数即可。

也能够引入配置文件,在不批改客户端代码的状况下更换和增加新的具体产品类。

毛病:

  • 简略工厂模式的工厂类繁多,负责所有产品的创立,职责过重,一旦异样,整个零碎将受影响。且工厂类代码会十分臃肿,违反高聚合准则。
  • 应用简略工厂模式会减少零碎中类的个数(引入新的工厂类),减少零碎的复杂度和了解难度
  • 零碎扩大艰难,一旦减少新产品不得不批改工厂逻辑,在产品类型较多时,可能造成逻辑过于简单
  • 简略工厂模式应用了 static 工厂办法,造成工厂角色无奈造成基于继承的等级构造。

利用场景

对于产品种类绝对较少的状况,思考应用简略工厂模式。应用简略工厂模式的客户端只须要传入工厂类的参数,不须要关怀如何创建对象的逻辑,能够很不便地创立所需产品。

代码实现

简略工厂模式的次要角色如下:

  • 简略工厂:是简略工厂模式的外围,负责实现创立所有实例的外部逻辑。工厂类的创立产品类的办法能够被外界间接调用,创立所需的产品对象。
  • 形象产品:是简略工厂创立的所有对象的父类,负责形容所有实例共有的公共接口。
  • 具体产品:是简略工厂模式的创立指标。

其结构图如下图所示。

kotlin代码实现

interface IProduct{    fun showName() :String}class Dog : IProduct{    override fun showName() = "dog"}class Cat : IProduct{    override fun showName() = "cat"}object AnimalFactory{    fun createAnimal(type:Int):IProduct{        return when(type){            1-> Dog()            2-> Cat()            else -> throw NullPointerException()        }    }}

简略工厂模式在Android中的理论利用

fragment 的构建

有时候,为了简化简略工厂模式,咱们能够将形象产品类和工厂类合并,将动态工厂办法移至形象产品类中。Fragment的创立应用简略工厂办法没有形象产品类,所以工厂类放到了实现产品类中。

class ListWorkFragment : BMvpFragment<ListWorkView ,ListWorkPresenter>(),ListWorkView,ISubjectView{        companion object {        @JvmStatic        fun newInstance(recommendTypeId: Int,                        termCode: String = "") =            ListWorkFragment().apply {                arguments = Bundle().apply {                    putInt("type", recommendTypeId)                    putString("code", termCode)                }            }    }

长处

  1. 在创立Fragment的时候,能够不须要管外部参数,而从内部输出
  2. Fragment举荐应用setArguments来传递参数,防止在横竖屏切换的时候Fragment主动调用本人的无参构造函数,导致数据失落。

Bitmap源码剖析

@UnsupportedAppUsage(maxTargetSdk = 28)    Bitmap(long nativeBitmap, int width, int height, int density,            boolean requestPremultiplied, byte[] ninePatchChunk,            NinePatch.InsetStruct ninePatchInsets) {        this(nativeBitmap, width, height, density, requestPremultiplied, ninePatchChunk,                ninePatchInsets, true);    }    // called from JNI and Bitmap_Delegate.    Bitmap(long nativeBitmap, int width, int height, int density,            boolean requestPremultiplied, byte[] ninePatchChunk,            NinePatch.InsetStruct ninePatchInsets, boolean fromMalloc) {        ...    }

看构造函数可知,无奈new出bitmap,那么怎么创立bitmap对象呢?

 BitmapFactory.decodeFile("")

外部源码

public static Bitmap decodeFile(String pathName) {    return decodeFile(pathName, null);}public static Bitmap decodeFile(String pathName, Options opts) {    Bitmap bm = null;    InputStream stream = null;    try {        stream = new FileInputStream(pathName);        bm = decodeStream(stream, null, opts);    } catch (Exception e) {        /*  do nothing.            If the exception happened on open, bm will be null.        */        Log.e("BitmapFactory", "Unable to decode stream: " + e);    } finally {        if (stream != null) {            try {                stream.close();            } catch (IOException e) {                // do nothing here            }        }    }    return bm;}public static Bitmap decodeStream(InputStream is, Rect outPadding, Options opts) {    // we don't throw in this case, thus allowing the caller to only check    // the cache, and not force the image to be decoded.    if (is == null) {        return null;    }    Bitmap bm = null;    Trace.traceBegin(Trace.TRACE_TAG_GRAPHICS, "decodeBitmap");    try {        if (is instanceof AssetManager.AssetInputStream) {            final long asset = ((AssetManager.AssetInputStream) is).getNativeAsset();            bm = nativeDecodeAsset(asset, outPadding, opts);        } else {            bm = decodeStreamInternal(is, outPadding, opts);        }        if (bm == null && opts != null && opts.inBitmap != null) {            throw new IllegalArgumentException("Problem decoding into existing bitmap");        }        setDensityFromOptions(bm, opts);    } finally {        Trace.traceEnd(Trace.TRACE_TAG_GRAPHICS);    }    return bm;}private static native Bitmap nativeDecodeStream(InputStream is, byte[] storage,        Rect padding, Options opts);/** * Set the newly decoded bitmap's density based on the Options. */private static void setDensityFromOptions(Bitmap outputBitmap, Options opts) {    if (outputBitmap == null || opts == null) return;    final int density = opts.inDensity;    if (density != 0) {        outputBitmap.setDensity(density);        final int targetDensity = opts.inTargetDensity;        if (targetDensity == 0 || density == targetDensity || density == opts.inScreenDensity) {            return;        }        byte[] np = outputBitmap.getNinePatchChunk();        final boolean isNinePatch = np != null && NinePatch.isNinePatchChunk(np);        if (opts.inScaled || isNinePatch) {            outputBitmap.setDensity(targetDensity);        }    } else if (opts.inBitmap != null) {        // bitmap was reused, ensure density is reset        outputBitmap.setDensity(Bitmap.getDefaultDensity());    }}

看下BitmapFactory的正文咱们能够看到,这个工厂反对从不同的资源创立Bitmap对象,包含files, streams, 和byte-arrays,然而调用关系都大同小异。