原型模型的简单使用

21 篇文章 0 订阅
19 篇文章 0 订阅

前言

原型模型的使用在Android里最大的体现是Intent,通过看源码不难发现,intent传值进去之后在startActivity之前会clone一份Intent,说回来原型模式其实就牵扯到拷贝问题,换一句话,预防对象被意外改动使用拷贝就是原型模式。

使用场景

1.类初始化操作复杂,牵扯到太多资源的。
2.一个对象需要提供给其他对象访问,那各个调用它的对象都可能更改它的值,但是更改的值只对该对象使用有效(如果移除更改别的地方也跟着改动,那应该考虑单例模式了)

简单实现

在开发中常常会存储一些参数,而这些参数不能够提供对外的修改方法,只能够提供私有的存储方法,在指定的时候调用,比如我们要写一个外卖地址存储模块,当用户修改地址之后并不立刻去修改缓存信息,而是等待接口返回之后再同步Client和Service的用户信息。抽象出一个User类为用户信息类,定义一个UserManager类。为User管理类。首先我们来看看User类:

package com.demo.prototype;

/**
 * Created by italkbb on 2017/12/13.
 */

public class User implements Cloneable{
    private String age;
    private String sex;
    private String name;
    private String address;
    private String phoneNumber;

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    /**
     * 复写clone方法,以便于获取用户实体的一个备份
     * @return
     * @throws CloneNotSupportedException
     */
    @Override
    protected User clone() throws CloneNotSupportedException {
        return  (User) super.clone();
    }
}

用户类里定义了私有的获取用户信息方法,只不过这个用户信息是一个备份,不会影响缓存实体本身。

下面单例模式在同级包下面定义一个用户管理类:

package com.demo.prototype;

/**
 * Created by italkbb on 2017/12/13.
 */

public class UserManager {
    private User mUser;
    private UserManager(){}

    public static UserManager getInstance(){
        return UserManagerHolder.mUserManager;
    }

    private static class UserManagerHolder{
        private static final UserManager mUserManager = new UserManager();
    }

    protected void setUserInfo(User user){
        mUser = user;
    }

    /**
     * 获取到clone的对象,这里外面做一个判空,以防万一
     * @return
     * @throws CloneNotSupportedException
     */
    public User getUserInfo() throws CloneNotSupportedException {
        return mUser.clone();
    }
}

管理类里面对外公布了获取用户信息备份的方法,但修改方法是私有的,不允许随便更改,那么用户信息接口请求回来之后必须要更改这些信息,已达到两边同步,那么假设有一个接口回调处理,我们模拟一个信息修改接口:

package com.demo.prototype;

/**
 * Created by italkbb on 2017/12/13.
 */

public interface ModifyInfo {
    // 信息修改成功调用的接口方法
    void modifySucceed(User user);

    // 信息修改失败调用的方法,这里面可以清理一些资源。
    void modifyFailed(Error error);
}

接下来在接口的实现类里面更改这个用户信息,注意我们应该吧接口回调实现类放在UserManager的同包目录,因为这是一个模块,所以我的设计就是把用户信息更新方法为包级私有。

package com.demo.prototype;

/**
 * Created by italkbb on 2017/12/13.
 */

public class ModifyInfoImpl implements ModifyInfo {

    @Override
    public void modifySucceed(User user) {
        // 获取得到服务器用户信息,同步到本地缓存
        // 单例模式获取管理类,通过管理类来同步用户数据
        UserManager.getInstance().setUserInfo(user);
    }

    @Override
    public void modifyFailed(Error error) {

    }
}

这样简单的原型模式就完成了,我们使用的时候只有接口回来才会修改用户信息,其他时候并没有权限去调用修改的方法。

关于拷贝

在上面的demo中,我们用到了clone,这种拷贝叫做深拷贝,拷贝对象的修改不会影响之前的对象,对于基本数据类型,用等号赋值的效果就是深拷贝的效果,但是对于非基本数据类型,等号只是一个浅拷贝的过程,更改拷贝数据,源数据也会跟着改变,所以在这个模式里面,应该尽可能使用深拷贝。

后记

任何模式都会有优缺点,原型模式的有点事避免了数据被莫名的改动,通过二进制拷贝要比new对象性能好很多,如果对象越多,这个优点就越明显;缺点就是clone时候,对象的构造函数不会执行,那么在构造函数执行相关操作,应该多考虑考虑,是否满足需求。我的邮箱redzkh@gmail.com,有错误还望指正。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值