原型模型的简单使用

来源:互联网 发布:vb编程界面 编辑:程序博客网 时间:2024/06/02 19:13

前言

原型模型的使用在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,有错误还望指正。

原创粉丝点击