设计模式(4)-对象创建型模式-Prototype模式

设计模式(4)-对象创建型模式-Prototype模式

大家好,又见面了,我是全栈君。

1.对象创建型模式

1.4          Protoype模式

1.4.1需求

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

1.4.2结构

设计模式(4)-对象创建型模式-Prototype模式

•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()并不会对其进行拷贝,需自行提供深拷贝;

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/116324.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号