美文网首页程序员设计模式
设计模式之原型模式(创建型)

设计模式之原型模式(创建型)

作者: smileNicky | 来源:发表于2019-02-17 16:16 被阅读9次

[TOC]

模式定义

原型模式(Prototype Pattern):原型模式是提供一个原型接口,提供原型的克隆,创建新的对象,是一种对象创建型模式。

模式结构

原型模式包括如下角色

  • Prototype :抽象原型类
  • ConcretePrototype:具体原型类
  • Client:客户类

原型模式类别

一个类包括另外一个成员变量,在使用原型模式进行对象克隆时,如果直接是通过super Cloneable接口的的clone方法,这种情况其实并不支持类中另外一些成员变量的克隆的,这种方法称之为浅克隆,所以浅克隆和深克隆的本质区别就是看其是否支持类中的成员变量的克隆。

综上,原型模式可以浅克隆和深克隆两种情况,其区别是是否支持类中的成员变量的克隆。

原型模式的浅克隆
原型模式在Java里的常用实现是通过类继承 JDK提供的Cloneable接口,重写 clone(),这种方法其实也可以称之为原型模式的浅克隆

public class A implements Cloneable 
{

    
    public Object clone()
    {
        A clone=null;
        try
        {
            clone=(A)super.clone();     
        }
        catch(CloneNotSupportedException e)
        {
            System.out.println("Clone failure!");
        }
        return clone;
    }
}

一般来说,clone方法符合:

  • 类型相同:对于任何对象a,a.clone().getClass() = a.getClass()
  • 内存地址不同:也可以说对于任何对象a,a.clone()!=a,克隆对象和原对象不是同一个对象
  • a对象的equals方法:对于任何对象a,a.clone().equals(a)

浅克隆的例子,例子来自《设计模式》一书的邮件复制

由于邮件对象包含的内容较多(如发送者、接收者、标题、内容、日期、附件等),某系统中现需要提供一个邮件复制功能,对于已经创建好的邮件对象,可以通过复制的方式创建一个新的邮件对象,如果需要改变某部分内容,无须修改原始的邮件对象,只需要修改复制后得到的邮件对象即可。使用原型模式设计该系统。在本实例中使用浅克隆实现邮件复制,即复制邮件(Email)的同时不复制附件(Attachment)。

附件类:

public class Attachment
{
    public void download()
    {
        System.out.println("下载附件"); 
    }
}

邮件类,浅克隆:

public class Email implements Cloneable 
{
    private Attachment attachment=null;
    
    public Email()
    {
        this.attachment=new Attachment();
    }
    
    public Object clone()
    {
        Email clone=null;
        try
        {
            clone=(Email)super.clone();     
        }
        catch(CloneNotSupportedException e)
        {
            System.out.println("Clone failure!");
        }
        return clone;
    }
    
    public Attachment getAttachment()
    {
        return this.attachment;
    }
    
    public void display()
    {
        System.out.println("查看邮件"); 
    }
    
}

客户端类:

public class Client
{
    public static void main(String a[])
    {
        Email email,copyEmail;
        
        email=new Email();
        
        copyEmail=(Email)email.clone();
        
        System.out.println("email==copyEmail?");
        System.out.println(email==copyEmail);
        
        System.out.println("email.getAttachment==copyEmail.getAttachment?"); 
        System.out.println(email.getAttachment()==copyEmail.getAttachment());           
    }
}

编译返回,第一个是false,第二个是true,由前面的理论可以知道,浅克隆对于成员变量是不支持克隆的,因为对象地址还是一样的

原型模式的深克隆

上面是浅克隆的实现,对于原型模式深克隆的实现一般是提供类的序列化来实现

附件类,注意要implements Serializable

import java.io.*;

public class Attachment implements Serializable
{
    public void download()
    {
        System.out.println("下载附件");
    }
}

邮件类,同样要实现Serializable接口

import java.io.*;

public class Email implements Serializable
{
    private Attachment attachment=null;

    public Email()
    {
        this.attachment=new Attachment();
    }

    public Object deepClone() throws IOException, ClassNotFoundException, OptionalDataException
    {
        //将对象写入流中
        ByteArrayOutputStream bao=new ByteArrayOutputStream();
        ObjectOutputStream oos=new ObjectOutputStream(bao);
        oos.writeObject(this);

        //将对象从流中取出
        ByteArrayInputStream bis=new ByteArrayInputStream(bao.toByteArray());
        ObjectInputStream ois=new ObjectInputStream(bis);
        return(ois.readObject());
    }

    public Attachment getAttachment()
    {
        return this.attachment;
    }

    public void display()
    {
        System.out.println("查看邮件");
    }

}

客户端类:


public class Client
{
    public static void main(String a[])
    {
        Email email,copyEmail=null;

        email=new Email();

        try{
            copyEmail=(Email)email.deepClone();
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }


        System.out.println("email==copyEmail?");
        System.out.println(email==copyEmail);

        System.out.println("email.getAttachment==copyEmail.getAttachment?");
        System.out.println(email.getAttachment()==copyEmail.getAttachment());
    }
}

编译返回,第一个是false,第二个是flase,由前面的理论可以知道,深克隆对于成员变量是支持克隆的,因为对象地址是一样的

原型管理器
原型管理器是原型模式的拓展
例子同样来自《设计模式》一书

import java.util.*;

interface MyColor extends Cloneable
{
    public Object clone();
    public void display();
}

class Red implements MyColor
{
   public Object clone()
   {
     Red r=null;
     try
     {
       r=(Red)super.clone();
     }
     catch(CloneNotSupportedException e)
     {  
  
     }
     return r;
   }
   public void display()
   {
     System.out.println("This is Red!");
   }
}

class Blue implements MyColor
{
   public Object clone()
   {
     Blue b=null;
     try
     {
       b=(Blue)super.clone();
     }
     catch(CloneNotSupportedException e)
     {  
  
     }
     return b;
   }
   public void display()
   {
     System.out.println("This is Blue!");
   }
}

class PrototypeManager 
{
   private Hashtable ht=new Hashtable();
   
   public PrototypeManager()
   {
      ht.put("red",new Red());
      ht.put("blue",new Blue());
   }
   
   public void addColor(String key,MyColor obj)
   {
      ht.put(key,obj);
   }
   
   public MyColor getColor(String key)
   {
      return (MyColor)((MyColor)ht.get(key)).clone();
   }
}

class Client
{
   public static void main(String args[])
   {
      PrototypeManager pm=new PrototypeManager();  
      
      MyColor obj1=(MyColor)pm.getColor("red");
      obj1.display();
      
      MyColor obj2=(MyColor)pm.getColor("red");
      obj2.display();
      
      System.out.println(obj1==obj2);
   }
}

模式应用

原型模式适用的场景

  • 保存对象的状态:对于要保存的状态不是很占内存的情况,可以适用原型模式和备忘录模式保存对象状态,如果对象占用太多内存,那就还是状态模式比较好

  • 创建新对象成本很大的情况:比如创建一个对象是需要查询很慢的SQL才能给对象赋值,这种情况就和适合用原型模式克隆对象,减少对象创建和查询

原型模式应用的场景

  • 对于很多软件的复制和粘贴实现其实也是原型模式的应用
  • Spring框架提供BeanUtils.copyProperties方法也是原型模式的应用

相关文章

  • 创建型设计模式——原型模式

    定义 原型模式是一个创建型的设计模式。用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。原型模式多用于...

  • 设计模式[4]-原型模式-Prototype Pattern

    1. 原型模式简介 原型模式(Prototype Pattern)是创建型设计模式,根据一个原型对象,通过Clon...

  • android常用设计模式

    26种设计模式 创建型设计模式[5] 单例模式,工厂模式,抽象工厂模式,建造模式,原型模式,[简单工厂模式] 结构...

  • 三、原型模式

    原型模式用于创建重复对象的同时保持性能,该模式属于创建型设计模式,是创建对象的最佳实现方式。 为什么要使用原型模式...

  • 初始设计模式之原型模式

    原型模式是什么? 原型模式怎么用?浅拷贝深拷贝 原型模式再理解 一、原型模式是什么? ​ 原型模式是一种创建型设计...

  • 设计模式之原型模式

    设计模式之原型模式 原型模式 属于 创建型模式,提供创建对象的最佳方式。 原型模式 简介 也就是 说 根据一个已有...

  • Java设计模式之04_Prototype(原型模式)

    更多Java设计模式:Java设计模式-目录 原型模式是一种简单、易使用的创建型设计模式,通过给出一个原型对象来指...

  • 设计模式之原型模式

    设计模式之原型模式 Intro 简介 原型模式,用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象 原...

  • S3. 原型模式

    原型模式(Prototype) baidu[www.baidu.com] 原型模式是一种创建型设计模式,其功能为复...

  • Objective-C 原型模式 -- 简单介绍和使用

    用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。Prototype原型模式是一种创建型设计模式,P...

网友评论

    本文标题:设计模式之原型模式(创建型)

    本文链接:https://www.haomeiwen.com/subject/fnigeqtx.html