zoukankan      html  css  js  c++  java
  • 设计模式(4)-对象创建型模式-Prototype模式

    1.对象创建型模式

    1.4          Protoype模式

    1.4.1需求

                    通过拷贝原形对象创建新的对象。

    1.4.2结构


    •P r o t o t y p e(Gr a p h i c)

    — 声明一个克隆自身的接口。

    •C o n c r e t e P r o t o t y p e(S t a ff、W h o l e N o t e、H a l fN o t e)

    — 实现一个克隆自身的操作。

    •  C l i e n t(G r a p h i c To o l)

    — 让一个原型克隆自身从而创建一个新的对象。

    1.4.3样例-C++             

    //Prototype.h
    #ifndef _PROTOTYPE_H_
    #define _PROTOTYPE_H_

    class Prototype
    {
    public:
                    virtual ~Prototype();
                    virtual Prototype*Clone()const = 0;
    protected:
                    Prototype();
    private:
    };

    class ConcretePrototype:public Prototype
    {
    public:
                    ConcretePrototype();
                    ConcretePrototype(const  ConcretePrototype& cp);
                    ~ConcretePrototype();
                    Prototype* Clone() const;
    protected:
    private:
    };

    #endif //~_PROTOTYPE_H_

    代码片断2:Prototype.cpp

    //Prototype.cpp

    #include"Prototype.h"
    #include<iostream>
    using namespace std;
    Prototype::Prototype()
    {
    }

    Prototype::~Prototype()
    {
    }

    Prototype* Prototype::Clone() const
    {
                    return 0;
    }

    ConcretePrototype::ConcretePrototype()
    {
    }

    ConcretePrototype::~ConcretePrototype()
    {
    }

    ConcretePrototype::ConcretePrototype(const  ConcretePrototype& cp)
    {
                    cout<<"ConcretePrototype copy..."<<endl;
    }

    Prototype* ConcretePrototype::Clone() const
    {
                    return newConcretePrototype(*this);
    }

    //main.cpp
    #include"Prototype.h"
    #include<iostream>
    using namespace std;

    int main(int argc,char*argv[])
    {
                    Prototype* p= newConcretePrototype();
                    Prototype* p1=p->Clone();
                    return 0;
    }

    注:这里仅仅是说明概念,没有涉及C++常见的深度拷贝问题.

    1.4.4 样例-JAVA

    Java中,原型模式能够非常easy地实现,仅仅要实现Cloneable这个标识性的接口,再覆盖该接口中的clone()方法,就可以“克隆”该实现类的不论什么一个对象。

    class ConcretePrototype02 implements Cloneable{ 
      private String name; 
      private ArrayList<String> nameList = new ArrayList<String>(); 

      public ConcretePrototype02(String name) { 
        this.name = name; 
        this.nameList.add(this.name); 
      } 
      //加入nameList中的对象 
      public void setName(String name) { 
        this.nameList.add(name); 
      } 
        
      public ArrayList<String> getNameList() { 
        return this.nameList; 
      } 
        
      //覆盖Object基类中的clone()方法,并扩大该方法的訪问权限,详细化返回本类型 
      public ConcretePrototype02 clone() { 
        ConcretePrototype02self = null
        try { 
          self= (ConcretePrototype02) super.clone(); 
          //下面这句是实现深拷贝的关键 
    //      self.nameList =(ArrayList<String>) this.nameList.clone(); 
        } catch (CloneNotSupportedException e) { 
          e.printStackTrace(); 
        } 
        return self; 
      } 


    //測试类 
    public class Client { 
      public static void main(String[] args) { 
        ConcretePrototype02prototype02 = new ConcretePrototype02("蚂蚁 ..."); 
        System.out.println(prototype02.getNameList()); 
         
        //通过clone获得一个拷贝 
        ConcretePrototype02fromClone02 = prototype02.clone(); 
        fromClone02.setName("小蚂蚁 ..."); 
        System.out.println(fromClone02.getNameList()); 
        System.out.println(prototype02.getNameList()); 
      } 
    }

    測试结果:

    拷贝之前的原型: [蚂蚁 ...]

    拷贝得到的对象: [蚂蚁 ..., 小蚂蚁 ...]

    拷贝之后的原型: [蚂蚁 ..., 小蚂蚁 ...]

    发现拷贝之后原来的对象持有的ArrayList<String>类型的nameList引用会随着拷贝得到的fromClone对象运行了setName()方法而改变。这不是我们想要的结果,由于这意味着原型以及拷贝得到的对象共享同一个引用变量,这是线程不安全的。当我们去掉    上面clone()方法中被凝视的语句之后再測试,得到结果例如以下:

    拷贝之前的原型: [蚂蚁 ...]

    拷贝得到的对象: [蚂蚁 ..., 小蚂蚁 ...]

    拷贝之后的原型: [蚂蚁 ...]

     

    Java中使用原型模式Prototype是相当简单的,仅仅要记住几点注意点,就能够方便地实现该模式了。

    因为使用clone()方法来拷贝一个对象是从内存二进制流中进行IO读写。所以拷贝得到一个对象是不会运行该对象所相应类的构造函数的。

    总结例如以下:

    1、构造函数不会被运行。

    2、类的成员变量中若有引用类型的变量(数组也是一种对象)。默认的clone()并不会对其进行拷贝,需自行提供深拷贝;

  • 相关阅读:
    梦断代码阅读笔记之二
    《需求工程——软件建模与分析》阅读笔记之四
    阿里云HttpDns接入
    Android电量优化-Battery Historian环境搭建及简单使用
    Crash监控的简单实现方案
    Flutter——比RichText更好用的富文本
    用终端命令行工具iTerm创建flutter项目
    Flutter——打包到TestFlight和安卓
    Flutter——数组以符号隔开转字符串
    某信反反越狱
  • 原文地址:https://www.cnblogs.com/yxwkf/p/5130196.html
Copyright © 2011-2022 走看看