观察者模式(结合代理模式)

概述

此观察模式是基于PanoramaImageView项目(github地址:https://github.com/gjiazhe/PanoramaImageView)的需求来实现的,功能上与原项目的
GyroscopeObserver基本相同,额外做了接口的完善并与代理模式进行结合,将观察者与被观察者解耦,更具拓展性。

观察者模式:

对于设计模式来说,uml类图最直观简明的阐述方式:

这里写图片描述

上图《大话设计模式》一书中对观察者模式uml类图的说明,这本书对于设计模式初学者是很不错的。
对于观察者模式的教程说明网上资源甚多,但核心就是上面的类图。一篇介绍比较全面的文章

代理模式:

上uml图:

这里写图片描述

上博客:代理模式

此次实现的观察者模式:

继续上uml类图:

这里写图片描述

实现的思路:

一:被观察者(即观察者模式中的subject,也被称为observed)的实现
接口:只有一个updata方法


public interface BaseObservedInterface<T> {
    void updata(T t);
}

GyroscopeObservedImpl(实现类):获取陀螺仪传感器并实现监听方法,将处理后的数据通过updata方法调用controller.updata()。(这里并不是正宗的代理模式,只是借用了代理的思想。为什么不直接调用controller.updata(),这里考虑了程序的可拓展性),代码如下

public class GyroscopeObservedImpl implements SensorEventListener, BaseObservedInterface<GyroscopeControllInterface> {
    private SensorManager mSensorManager;
    private double rotateRadianX;
    private double rotateRadianY;
    private double rotateRadianZ;
    private double rotateRadian;
    private long lastTimestamp;
    private static final float NS2S = 1.0f / 1000000000.0f;
    private static final int rotateAroundX = 1;
    private static final int rotateAroundY = 2;
    private static final int rotateAroundZ = 3;
    private static int type;
    private GyroscopeControllInterface gyroscopeControllInterface;

    public GyroscopeObservedImpl(GyroscopeControllInterface gyroscopeControllInterface) {
        this.gyroscopeControllInterface = gyroscopeControllInterface;
    }

    public void register(Context context) {
        Log.e("TAG", "register: " + "注册了");
        if (mSensorManager == null) {
            mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
        }
        Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
        mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_FASTEST);
    }

    public void unregister() {
        Log.e("TAG", "register: " + "解除注册了");
        if (mSensorManager != null) {
            mSensorManager.unregisterListener(this);
            mSensorManager = null;
        }
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        if (lastTimestamp == 0) {
            lastTimestamp = event.timestamp;
            return;
        }
        float angularX = Math.abs(event.values[0]);
        float angularY = Math.abs(event.values[1]);
        float angularZ = Math.abs(event.values[2]);

        final float dT = (event.timestamp - lastTimestamp) * NS2S;
        if (angularX > angularY + angularZ) {  //围绕x轴运动,即手机上下摆动(脑补拿手机打手板的动作)
            rotateRadianX += event.values[0] * dT;
            rotateRadian = rotateRadianX;
            type = rotateAroundX;
        } else if (angularY > angularX + angularZ) {//围绕y轴运动,即手机左右摆动(脑补四驱兄弟里面的“旋风冲锋龙卷风”)
            rotateRadianY += event.values[1] * dT;
            type = rotateAroundY;
            rotateRadian = rotateRadianY;
        } else {//围绕Z轴运动,可以理解为手机放在桌子上转圈
            rotateRadianZ += event.values[2] * dT;
            type = rotateAroundZ;
            rotateRadian = rotateRadianZ;
        }
        updata(gyroscopeControllInterface);
        lastTimestamp = event.timestamp;
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }

    @Override
    public void updata(GyroscopeControllInterface gyroscopeControllInterface) {
        gyroscopeControllInterface.updata(rotateRadian, type);
    }
}

二:Controller的实现:我们将观察者的注册,解除从Observed(Subject)中提出来,交予controller实现。

BaseControllerInterface接口:这个接口我们定义了对观察者的注册,解除以及更新的基本方法


public interface BaseControllerInterface<T> {
    void attach(T t);

    void detach(T t);

    void updata();
}

GyroscopeControllInterface接口:这个接口根据需求重载了updata()方法

public interface GyroscopeControllInterface extends BaseControllerInterface<ImgvObserve> {
    void updata(double rotateRadian, int type);
}

GyroscopeControllerImpl(实现类):没啥说的,很简单,代码如下

public class GyroscopeControllerImpl implements GyroscopeControllInterface {
    private List<ImgvObserve> observaeList;

    public GyroscopeControllerImpl() {
        observaeList = new ArrayList<>();
    }

    @Override
    public void updata(double rotateRadian, int type) {
        for (ImgvObserve imgvObserve : observaeList) {
            imgvObserve.updata(rotateRadian, type);
        }
    }


    @Override
    public void attach(ImgvObserve observer) {
        if (!observaeList.contains(observer)) {
            observaeList.add(observer);
        }
    }

    @Override
    public void detach(ImgvObserve observer) {
        if (observaeList.contains(observer)) {
            observaeList.remove(observer);
        }
    }

    @Override
    public void updata() {

    }
}

三:观察者的实现
接口:这里是根据需求直接写的接口(这里的updata方法并不一定要和上边一样,可以根据需求灵活改动)


public interface ImgvObserve {
    void updata(double rotateRadian, int type);
}

PanoramaImageView(实现类):在原作者的PanoramaImageView基础上做的改动,自己重写了一遍核心方法,有部分细节会不太一样。代码较多,这里只贴出观察者相关代码

 @Override
    public void updata(double rotateRadian, int type) {
        //如果type与当前图片的type一致
        if (orientation == type) {
            //限制旋转弧度最大为maxRotateRadian
            if (rotateRadian >= maxRotateRadian) {
                rotateRadian = maxRotateRadian;
            } else if (rotateRadian <= -maxRotateRadian) {
                rotateRadian = -maxRotateRadian;
            }
            //计算出比例值
            progress = (float) (rotateRadian / maxRotateRadian);
            invalidate();
        }
    }

源码地址:https://github.com/Ljy2016/PanoramaImageView

总结:

观察者模式在android开发中是应用较为普遍的模式,像eventBus,Rxjava等事件管理框架都是基于观察者模式实现的。此次的仿写轮子固然收获很多,但是限于经验还远不够丰富,视野比较狭隘,对于接口的设计,模式的应用还存在很多的问题,颇有些坐井观天的感觉,那就努力的向上爬吧,爬出井口才是更大的天地。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值