设计模式系列11---快速拷贝的原型模型

enter image description here
早年一直有新闻报道,XXX拖欠农民工工资的情况,甚至没有和员工签订合同的。这种做法当然不好,但现实也是挺残酷的,上门为了利润,就这么做,能省就省,遇到什么工伤之类的都不用赔,因为没有合同,你怎么说工伤呢?
这和大公司开一家小公司,去做特定的项目类似,规避风险。

假设我们有一份 重要的合同,需要一式两份保存,每人个一份。
这时候我们要快速的备份一份,因为内容完全一样,这时候就可以用原型模型

代码实现

我们写一个合同类,里面有合同的日期,合同的具体内容,签名的人的列表。
就像下面这个这样。

public class Contract  implements  Cloneable{

    public String context;
    public List<String> sign;
    public Date date;

    @Override
    public Contract clone(){

        try {
            Contract newContract= (Contract) super.clone();
            newContract.context=this.context;
            newContract.date=this.date;
            newContract.sign=this.sign;

            return  newContract;
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }

        return  null;
    }
}

我们的合同实现了Cloneable接口,所以我们可以快速的copy一份
具体如下

public class client {

    public static void main(String[] args) {
        Contract contract=new Contract();
        contract.context="this is contract text";
        contract.date=new Date(System.currentTimeMillis());

        List<String> signs=new ArrayList<>();
        signs.add("jack");
        signs.add("tom");
        contract.sign=signs;

        Contract mContract=contract.clone();

    }
}

好了,我们的原型模型实际说的就是这样,快速的复制一份。
不过有点需要提示的,就是这是一种浅拷贝
并没有做到完全的独立的两份。

下面的例子就可以告诉你结果。
我们简单的修改前面的例子,加多一点修改

public static void main(String[] args) {
       Contract originalContract=new Contract();
       originalContract.context="this is contract text";
       originalContract.date=new Date(System.currentTimeMillis());

       List<String> signs=new ArrayList<>();
       signs.add("jack");
       signs.add("tom");
       originalContract.sign=signs;

       Contract mCopyContract=originalContract.clone();
       mCopyContract.context="change the context";

       mCopyContract.sign.add("rose");
       System.out.println("oriContext=" + originalContract.context + ", copyContext=" + mCopyContract.context);

       System.out.println("oriSign ="+ originalContract.sign +" copySign="+mCopyContract.sign);

   }

我们拷贝后,修改我们的合同的内容,同时在拷贝版的合同加多rose的签名。理论上来说,我们的合同时一式两份,应该互不相干的。对原本的合同也不应该有任何影响,带着这样的判断,我们看下打印的内容。

oriContext=this is contract text, copyContext=change the context

oriSign =[jack, tom, rose] copySign=[jack, tom, rose]

我们看到我们的合同的内容是两份不一样,不过我们的签名!居然两份都有了,这不科学啊!

如果你曾经学过C/C++,这个就好结实,对于Sign的复制,他们就是给了指针,单纯的引用,并没有给我们重现开辟一个地方来保存!

所以我们需要修改原来的复制的地方!
改成深拷贝的。

public ArrayList<String> sign; 

 @Override
 public Contract clone(){

     try {
         Contract newContract= (Contract) super.clone();
         newContract.context=this.context;
         newContract.date=this.date;
         newContract.sign= (ArrayList<String>) this.sign.clone();//注意这里。

         return  newContract;
     } catch (CloneNotSupportedException e) {
         e.printStackTrace();
     }

     return  null;
 }

我们修改了我们的sign是一个具体的ArrayList类型,同时复制的时候加多clone()调用。

现在我们就可以安心快速的复制一个内容了,很好。

后记

这个原型模型应该是这些模型中最简单的吧,
因为他实际可以简单说的成就是一样事情,拷贝。
拷贝我们原来的东西,而且我们的java语言已经提供了这个特性接口。

不过有一些需要提下的,就是这个原型模型比较适合构造成本比较高的,或者构造较为麻烦的情况,特别是一个循环里面生成大量的对象情况,因为他背后是在内存中二进制流的拷贝,所以他的构造函数是
不会被执行的,这个需要特别注意!!

对于简单的,还是使用new一个好。

写了这么多篇设计模式的内容,回去重新看了写的前面的内容,
整体写得内容的表述还是很一般一般的,但可以看到有逐渐的改善!
这是一个挺好的事,虽然我写的不是很通俗易懂,但继续写的过程,不断有一些改善,这就很好了。同时也回去修改一些错误,感觉这就比没写文章时候更好了,这就值了。

热评文章