Utilice el modelo de cadena de responsabilidad para transformar el filtrado de procesamiento de código

Introducción a la escena

Cuando la aplicación pasa al primer plano desde el fondo, salta a la página de inicio para mostrar el anuncio en pantalla, que es un escenario relativamente común. A menudo necesitamos agregar algunas condiciones de control, no en todos los casos se omitirán los anuncios de pantalla, entonces la experiencia del usuario será mala, por lo que habrá una serie de condiciones de filtro.

Plan inicial

Al principio fue así:

  1. Determina si necesitas bloquear desde una página determinada
  2. Canal de juicio
  3. Intervalo de control de tiempo y límite de frecuencia según el contenido de la interfaz
       if (activity instanceof SplashActivity) {
            //启动页
            return;
        }
        if (activity instanceof LockScreenActivity) {
            //锁屏
            return;
        }
        if (activity instanceof AlcWidgetBaseConfigActivity) {
            //组件设置
            return;
        }
        if(AlcChannelUtil.isHuawei(this)){
            return;
        }
        String data = OnlineData.getInstance().getKey(activity, "go_splash_open", "");
        int status = 0;
        int oneDayMaxCount = 5;
        //120秒
        int offsetTime = 60;
        if (!TextUtils.isEmpty(data)) {
            try {
                JSONObject object = new JSONObject(data);
                status = object.optInt("isOpen");
                offsetTime = object.optInt("offsetTime");
                oneDayMaxCount = object.optInt("oneDayMaxCount");
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        boolean isOpen = status == 1;
        //转成毫秒
        offsetTime = offsetTime * 1000;
        if (isOpen) {
            //如果打开
            long lastSplashTime = (long) SPUtils.get(activity, "lastSplashTime", 0L);
            //并且时间间隔大于设置的时间间隔
            if ((System.currentTimeMillis() - lastSplashTime) > offsetTime) {
                //再判断次数是否达到上限
                //判断是否是今天
                int todayOpenCount = 0;
                if (TimeUtils.isSameDay(lastSplashTime)) {
                    todayOpenCount = (int) SPUtils.get(activity, "todayOpenCount", 0);
                }
                if (todayOpenCount < oneDayMaxCount) {
                    //小于这个次数,进入开屏页,保存这一次的时间,更新今天展开次数
                    SPUtils.put(activity, "lastSplashTime", System.currentTimeMillis());
                    todayOpenCount++;
                    SPUtils.put(activity, "todayOpenCount", todayOpenCount);
                    Intent goSplash = new Intent(activity, SplashActivity.class);
                    goSplash.putExtra("isFromOtherApp", true);
                    activity.startActivity(goSplash);
                }
            }
        }

Todo escrito en un solo lugar, el código está inflado y la escalabilidad también es pobre. Si agrega o elimina condiciones más tarde, lo modificará directamente aquí. Se siente inapropiado, así que pensé en usar el modelo de cadena de responsabilidad para transformarlo.

Mejorar

Definir clases básicas

Primero defina tres clases básicas, una es la interfaz del interceptor, una es la Cadena que se usa para conectar todos los interceptores y la otra es el objeto bean procesado por el interceptor.

public interface BaseSplashAdInterceptor {
    /**
     * 进行处理过滤,比如修改是否跳转广告、修改广告类型等
     *
     * @param adStatusBean
     */
    void doProcess(SplashAdStatusBean adStatusBean);
}

Clase de cadena

public class SplashAdChain {
    private List<BaseSplashAdInterceptor> mChains;

    /**
     * 添加拦截器
     * @param interceptor
     * @return
     */
    public SplashAdChain addInterceptor(BaseSplashAdInterceptor interceptor) {
        if (mChains == null) {
            mChains = new ArrayList<>();
        }
        mChains.add(interceptor);
        return this;
    }

    /**
     * 处理拦截操作
     * @param adStatusBean
     */
    public void doProcess(SplashAdStatusBean adStatusBean) {
        if (mChains != null) {
            for (BaseSplashAdInterceptor interceptor : mChains) {
                interceptor.doProcess(adStatusBean);
            }
        }
    }
}

Clase de objeto de operación:

public class SplashAdStatusBean implements Serializable {
    /**
     * 是否要跳转启动页广告
     */
    private boolean isNeedGoSplashAd;
    /**
     * 广告类型
     */
    private int splashAdType;
    /**
     * 从哪里来的
     */
    private Activity currentActivity;
    //...set和get方法 ,构造方法等
}

Establecer interceptor

Luego configure el interceptor de acuerdo con las condiciones requeridas, por ejemplo:

/**
 * 过滤Activity
 *
 * @author moore
 * @date 2019/8/5
 */
public class SplashAdActivityInterceptor implements BaseSplashAdInterceptor {

    @Override
    public void doProcess(SplashAdStatusBean adStatusBean) {
        if (adStatusBean.isNeedGoSplashAd()) {
            //如果需要跳转,再进行过滤
            Activity currentActivity = adStatusBean.getCurrentActivity();
            if (currentActivity == null) {
                adStatusBean.setNeedGoSplashAd(false);
                return;
            }
            if (currentActivity instanceof SplashActivity) {
                //启动页
                adStatusBean.setNeedGoSplashAd(false);
                return;
            }
            if (currentActivity instanceof LockScreenActivity) {
                //锁屏
                adStatusBean.setNeedGoSplashAd(false);
                return;
            }
            if (currentActivity instanceof AlcWidgetBaseConfigActivity) {
                //组件设置
                adStatusBean.setNeedGoSplashAd(false);
                return;
            }
        }
    }
}

Las demás condiciones son las mismas, muévelo al interceptor para operar, y clasifícalos. Como controlar el tiempo, controlar el número de veces, controlar el tipo de publicidad, etc.

Usar interceptor

Después de definir estas condiciones, puede usarlo, agregarlo según sea necesario y, finalmente, obtener un objeto procesado por cada interceptor. De acuerdo con algunos valores en este objeto, continúe con el siguiente paso.

        //拦截过滤不需要跳转启动页的情况
        SplashAdStatusBean statusBean = new SplashAdStatusBean(true, 5, activity);
        SplashAdChain chain = new SplashAdChain()
                .addInterceptor(new SplashAdActivityInterceptor())
                .addInterceptor(new SplashAdChannelInterceptor())
                .addInterceptor(new SplashAdTimesInterceptor());
        chain.doProcess(statusBean);
        //拦截后如果需要跳转,那就跳转吧~~~
        if (statusBean.isNeedGoSplashAd()) {
            SPUtils.put(activity, "lastSplashTime", System.currentTimeMillis());
            SPUtils.put(activity, "todayOpenCount", (statusBean.getTodayOpenCount() + 1));
            Intent goSplash = new Intent(activity, SplashActivity.class);
            goSplash.putExtra("isFromOtherApp", true);
            activity.startActivity(goSplash);
        }

Conclusión

Tal división aumentará significativamente el número de clases, pero podemos ver estas operaciones de filtrado e interceptación más claramente, y podemos hacer cambios más claramente en el futuro, reduciendo el acoplamiento de código.

Supongo que te gusta

Origin blog.csdn.net/lizebin_bin/article/details/98482096
Recomendado
Clasificación