use factory pattern for decoders
diff --git a/library/src/com/davemorrissey/labs/subscaleview/SubsamplingScaleImageView.java b/library/src/com/davemorrissey/labs/subscaleview/SubsamplingScaleImageView.java
index 69aaf71..30259ef 100644
--- a/library/src/com/davemorrissey/labs/subscaleview/SubsamplingScaleImageView.java
+++ b/library/src/com/davemorrissey/labs/subscaleview/SubsamplingScaleImageView.java
@@ -46,11 +46,12 @@
 import android.view.View;
 
 import com.davemorrissey.labs.subscaleview.R.styleable;
+import com.davemorrissey.labs.subscaleview.decoder.CompatDecoderFactory;
 import com.davemorrissey.labs.subscaleview.decoder.DecoderFactory;
 import com.davemorrissey.labs.subscaleview.decoder.ImageDecoder;
 import com.davemorrissey.labs.subscaleview.decoder.ImageRegionDecoder;
-import com.davemorrissey.labs.subscaleview.decoder.SkiaImageDecoderFactory;
-import com.davemorrissey.labs.subscaleview.decoder.SkiaImageRegionDecoderFactory;
+import com.davemorrissey.labs.subscaleview.decoder.SkiaImageDecoder;
+import com.davemorrissey.labs.subscaleview.decoder.SkiaImageRegionDecoder;
 
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
@@ -198,8 +199,8 @@
     // Tile and image decoding
     private ImageRegionDecoder decoder;
     private final Object decoderLock = new Object();
-    private DecoderFactory<? extends ImageDecoder> bitmapDecoderFactory = new SkiaImageDecoderFactory();
-    private DecoderFactory<? extends ImageRegionDecoder> regionDecoderFactory = new SkiaImageRegionDecoderFactory();
+    private DecoderFactory<? extends ImageDecoder> bitmapDecoderFactory = new CompatDecoderFactory<ImageDecoder>(SkiaImageDecoder.class);
+    private DecoderFactory<? extends ImageRegionDecoder> regionDecoderFactory = new CompatDecoderFactory<ImageRegionDecoder>(SkiaImageRegionDecoder.class);
 
     // Debug values
     private PointF vCenterStart;
@@ -1973,12 +1974,26 @@
     }
 
     /**
+     *
+     * Swap the default region decoder implementation for one of your own. You must do this before setting the image file or
+     * asset, and you cannot use a custom decoder when using layout XML to set an asset name. Your class must have a
+     * public default constructor.
+     * @param regionDecoderClass The {@link ImageRegionDecoder} implementation to use.
+     */
+    public final void setRegionDecoderClass(Class<? extends ImageRegionDecoder> regionDecoderClass) {
+        if (regionDecoderClass == null) {
+            throw new IllegalArgumentException("Decoder class cannot be set to null");
+        }
+        this.regionDecoderFactory = new CompatDecoderFactory<ImageRegionDecoder>(regionDecoderClass);
+    }
+
+    /**
      * Swap the default region decoder implementation for one of your own. You must do this before setting the image file or
      * asset, and you cannot use a custom decoder when using layout XML to set an asset name.
      * @param regionDecoderFactory The {@link DecoderFactory} implementation that produces {@link ImageRegionDecoder}
      *                             instances.
      */
-    public final void setRegionDecoderClass(DecoderFactory<? extends ImageRegionDecoder> regionDecoderFactory) {
+    public final void setRegionDecoderFactory(DecoderFactory<? extends ImageRegionDecoder> regionDecoderFactory) {
         if (regionDecoderFactory == null) {
             throw new IllegalArgumentException("Decoder factory cannot be set to null");
         }
@@ -1987,6 +2002,19 @@
 
     /**
      * Swap the default bitmap decoder implementation for one of your own. You must do this before setting the image file or
+     * asset, and you cannot use a custom decoder when using layout XML to set an asset name. Your class must have a
+     * public default constructor.
+     * @param bitmapDecoderClass The {@link ImageDecoder} implementation to use.
+     */
+    public final void setBitmapDecoderClass(Class<? extends ImageDecoder> bitmapDecoderClass) {
+        if (bitmapDecoderClass == null) {
+            throw new IllegalArgumentException("Decoder class cannot be set to null");
+        }
+        this.bitmapDecoderFactory = new CompatDecoderFactory<ImageDecoder>(bitmapDecoderClass);
+    }
+
+    /**
+     * Swap the default bitmap decoder implementation for one of your own. You must do this before setting the image file or
      * asset, and you cannot use a custom decoder when using layout XML to set an asset name.
      * @param bitmapDecoderFactory The {@link DecoderFactory} implementation that produces {@link ImageDecoder} instances.
      */
diff --git a/library/src/com/davemorrissey/labs/subscaleview/decoder/CompatDecoderFactory.java b/library/src/com/davemorrissey/labs/subscaleview/decoder/CompatDecoderFactory.java
new file mode 100644
index 0000000..daf9dfa
--- /dev/null
+++ b/library/src/com/davemorrissey/labs/subscaleview/decoder/CompatDecoderFactory.java
@@ -0,0 +1,20 @@
+package com.davemorrissey.labs.subscaleview.decoder;
+
+import android.support.annotation.NonNull;
+
+/**
+ * Compatibility factory to instantiate decoders with empty public constructors.
+ * @param <T> The base type of the decoder this factory will produce.
+ */
+public class CompatDecoderFactory <T> implements DecoderFactory<T> {
+  private Class<? extends T> clazz;
+
+  public CompatDecoderFactory(@NonNull Class<? extends T> clazz) {
+    this.clazz = clazz;
+  }
+
+  @Override
+  public T make() throws IllegalAccessException, InstantiationException {
+    return clazz.newInstance();
+  }
+}
diff --git a/library/src/com/davemorrissey/labs/subscaleview/decoder/DecoderFactory.java b/library/src/com/davemorrissey/labs/subscaleview/decoder/DecoderFactory.java
new file mode 100644
index 0000000..634904d
--- /dev/null
+++ b/library/src/com/davemorrissey/labs/subscaleview/decoder/DecoderFactory.java
@@ -0,0 +1,13 @@
+package com.davemorrissey.labs.subscaleview.decoder;
+
+/**
+ * Interface for decoder (and region decoder) factories.
+ * @param <T> the class of decoder that will be produced.
+ */
+public interface DecoderFactory<T> {
+  /**
+   * Produce a new instance of a decoder with type {@link T}.
+   * @return a new instance of your decoder.
+   */
+  T make() throws IllegalAccessException, InstantiationException;
+}