移动架构师-设计模式篇 《原型模式》

原型模式,对于开发者而言,或陌生,或熟悉,但是都应该很熟悉Cloneable接口。通过Cloneable接口,我们可以很容易的复制一个对象副本来单独使用,当然,这取决于Class是否实现了该接口以及如何实现。

原型模式是创建型的设计模式之一。官方而言,原型模式的作用是用指定原型对象来创建一个新的对象;从本身的功能与意义来理解的话,我们可以举个日常的例子。

我们应该都写过周报或日报,但是我们在写周报或日报的时候,除非第一次,否则大多数人的做法都是复制上一次周报的文件,修改文件名称,并修改部分周报内容,然后提交。为什么呢? 因为一我们已经有了一个类似的文件, 二则新的文件或许与旧的文件内容不同,但很多内容却是相同的。复用上一次的,省时省力,何乐而不为呢?

其实原型模式也是这样的。比如有一个产品A, A有100个字段;现在我们想要创建一个产品B,发现B很多特点和A都一样,可能部分属性是不同的;此时你会怎么做呢 ? 手动创建一个新的对象,还是从A的副本修改少部分属性呢 ? 答案显而易见。直接描述不够形象, 那么来一段简单的代码。

// 这是一个学生类,很简单!
public class Student implements Cloneable {
        public String name;
        public int age;
        public int sex;

        public Student(Student stu) {
             this.name = stu.name;
             this.age = stu.age;
             this.sex = stu.sex;
        }

        @override
        public Object clone() {
            return new Student(this);
        }
}
pubic class Main {
  
      public static void main(String[] args) {
                  // 有一个学生,小明
                  Student stu_xiaoming = new Student();
                  stu_xiaoming.name = "xiaoming";
                  stu_xiaoming.age = 18;
                  stu_xiaoming.sex = 1;  
                  
                  // 小明有一个发小 小毛,同班同读,也是18岁, 男孩
                  // 如果是你,你怎么生成这个发小的对象呢 ?
                  // 这就是原型模式的作用

                  Student stu_faxiao = stu_xiaoming.clone();
                  stu_faxiao.name = "xiaomao"; 
      }
}

通过上面的描述与例子,我想已经都猜到了原型模式的作用了。可能有人会说, 就3个属性罢了,复制一下也是很快的; 但是在开发中, 可能一个产品会有几十个几百个属性,都要复制吗 ?而且复制会产生大量的类似代码,无论对结构,以及开发效率都是不利的。

它主要面对的问题是:“某些结构复杂的对象”的创建工作;由于需求的变化,这些对象经常面临着剧烈的变化,但是他们却拥有比较稳定一致的接口。

深拷贝与浅拷贝
既然聊到复制, 我们来聊一下深拷贝与浅拷贝的问题。其实很好理解:
1.基本变量如int,boolean,double等类型的变量采用=赋的是值,如

int a = 10; 
int b = a;
int b = 5;
// 此时a = 10, b = 5.  b的赋值不会影响a

2.引用变量如List,String,数组等引用型的变量采用=赋得是址,即原引用和被赋值引用指向同一个地址,如

int[] a = new int[]{1,2,3,4};
int[] b = a;
b[3] = 5;
// 此时 a与b都是[1,2,3,5]。 b赋值给a,则a与b指向同一块内存空间,a与b对内存空间的修改,都同时生效 

3.Class的属性既包含基本类型,也包含引用类型;Class中所有的变量以及嵌套变量都是深拷贝,那么Class才是深拷贝

public class A implements Colneable {
    public int a; // 基本类型由于理论1,赋值后都是独立的
    public B b; // 引用对象如果

    @override 
    public Object clone() {
        A c = new A();
        c.a = this.a; // 基本类型不影响
        c.b = this.b; // 这里b是浅复制,此时两个引用指向同一内存, 相互影响
        // 以下是深复制,属性赋值后, 两者相互独立
        B d = new B();
        d.v = this.b.v;
        c.b = d;
    }
}

public class B {
        public int v;
}

最后的最后,结合Android的源码,来看一下原型模式的经典实现。今天的嘉宾是Intent, 大家可以借鉴~

// 片段1 实现Cloneable接口
public class Intent implements Parcelable, Cloneable {
...
// 片段2 接下来看一下clone的实现
   @Override
    public Object clone() {
        return new Intent(this);
    }
// 片段3 大家一定会好奇,构造方法才是关键,那构造方法里是什么呢 ?
public Intent(Intent o) {
        this.mAction = o.mAction;
        this.mData = o.mData;
        this.mType = o.mType;
        this.mPackage = o.mPackage;
        this.mComponent = o.mComponent;
        this.mFlags = o.mFlags;
        this.mContentUserHint = o.mContentUserHint;
        this.mLaunchToken = o.mLaunchToken;
        if (o.mCategories != null) {
            this.mCategories = new ArraySet<String>(o.mCategories);
        }
        if (o.mExtras != null) {
            this.mExtras = new Bundle(o.mExtras);
        }
        if (o.mSourceBounds != null) {
            this.mSourceBounds = new Rect(o.mSourceBounds);
        }
        if (o.mSelector != null) {
            this.mSelector = new Intent(o.mSelector);
        }
        if (o.mClipData != null) {
            this.mClipData = new ClipData(o.mClipData);
        }
    }
// 以上三步实现经典原型模式,同单例模式的讲解,借助官方的源码来完成我们自己的设计模式,才完美!

从本篇可以看出, 原型模式是很简单的,也好理解。原型模式主要解决了复杂对象的创建问题,它有什么优点和缺点呢 ?如下

1.隐藏了创建的细节,我们只知道clone生成一个副本,但是怎么生成,who knows ?
2.比直接创建一个对象更有效率,特别是复杂对象,因为它操作内存中的二进制流
3.省时省力省代码,复制很low,还会造成多余的代码,多次使用也很麻烦;总之复用比复制好太多


原型模式很简单, 本篇文章亦是,如果你觉得有收获,不妨为我打Call !!!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容