面向对象设计模式之---原型模式(Prototype Pattern)
2018-03-08 20:06
453 查看
原型模式的定义是:
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
这个概念看上去很抽象,其实质就是我们在编程中经常用到的对象复制,然后我们不免又要提到一个老生常谈的话题浅复制与深复制。
先看一下原型模式的UML类图吧:
其中,Prototype是一个原型的抽象类或借口,它里面有一个共有方法,叫clone。ConcretePrototype1与ConcretePrototype2是两个具体的实例,继承或实现了Prototype。这就对应了定义中用原型实例指定创建对象的种类。Client是客户端类,它与Prototype是关联的关系,即在Client类的实例中,有Prototype的对象。客户端可以通过调用Prototype的clone方法来对实现了Prototype的ConcretePrototype1或ConcretePrototype2的对象进行复制来创建新对象,这样比new会有更高的执行效率。
至于它的应有场景,我就拿《大话设计模式》中的例子吧,书中举了一个求职简历的例子,我们投公司一般都是一投好几家,简历也要准备好几份,有的还需要针对公司和职位量身定制部分内容,如果拿软件来生成简历,就比较适合使用原型模式来设计。
现在来谈谈浅复制与深复制的问题,所谓浅复制,简而言之,就是在对象中的非引用类型都会被逐位复制,引用类型复制的是引用,也就是说,在复制后的对象中,如果原有对象中含有引用类型的话,那么复制的对象与原对象指向同一个引用类型,这里的引用类型指的是数组、其他对象实例等。浅复制只做到了原对象与复制对象的相对独立;而深复制就是连引用类型也跟着复制了,原对象与复制对象完全独立。
这个例子我们用java来实现,在Java中有一个借口替我们实现好了Prototype,这个接口叫做cloneable。Sun官方的声明如下
public interface Cloneable
此类实现了 Cloneable 接口,以指示 Object.clone() 方法可以合法地对该类实例进行按字段复制。
如果在没有实现 Cloneable 接口的实例上调用 Object 的 clone 方法,则会导致抛出 CloneNotSupportedException 异常。
按照惯例,实现此接口的类应该使用公共方法重写 Object.clone(它是受保护的)。请参阅 Object.clone(),以获得有关重写此方法的详细信息。
注意,此接口不 包含 clone 方法。因此,因为某个对象实现了此接口就克隆它是不可能的。即使 clone 方法是反射性调用的,也无法保证它将获得成功。
注意红字,也就是说,这个接口告诉计算机,这个类是可复制的。clone默认实现的是浅复制,下面就举一个利用原型模式和cloneable接口实现深复制的例子。在简历中一般包含有工作经验,我们就把它抽象出一个类。
代码实例如下:
运行结果如下:
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
这个概念看上去很抽象,其实质就是我们在编程中经常用到的对象复制,然后我们不免又要提到一个老生常谈的话题浅复制与深复制。
先看一下原型模式的UML类图吧:
其中,Prototype是一个原型的抽象类或借口,它里面有一个共有方法,叫clone。ConcretePrototype1与ConcretePrototype2是两个具体的实例,继承或实现了Prototype。这就对应了定义中用原型实例指定创建对象的种类。Client是客户端类,它与Prototype是关联的关系,即在Client类的实例中,有Prototype的对象。客户端可以通过调用Prototype的clone方法来对实现了Prototype的ConcretePrototype1或ConcretePrototype2的对象进行复制来创建新对象,这样比new会有更高的执行效率。
至于它的应有场景,我就拿《大话设计模式》中的例子吧,书中举了一个求职简历的例子,我们投公司一般都是一投好几家,简历也要准备好几份,有的还需要针对公司和职位量身定制部分内容,如果拿软件来生成简历,就比较适合使用原型模式来设计。
现在来谈谈浅复制与深复制的问题,所谓浅复制,简而言之,就是在对象中的非引用类型都会被逐位复制,引用类型复制的是引用,也就是说,在复制后的对象中,如果原有对象中含有引用类型的话,那么复制的对象与原对象指向同一个引用类型,这里的引用类型指的是数组、其他对象实例等。浅复制只做到了原对象与复制对象的相对独立;而深复制就是连引用类型也跟着复制了,原对象与复制对象完全独立。
这个例子我们用java来实现,在Java中有一个借口替我们实现好了Prototype,这个接口叫做cloneable。Sun官方的声明如下
public interface Cloneable
此类实现了 Cloneable 接口,以指示 Object.clone() 方法可以合法地对该类实例进行按字段复制。
如果在没有实现 Cloneable 接口的实例上调用 Object 的 clone 方法,则会导致抛出 CloneNotSupportedException 异常。
按照惯例,实现此接口的类应该使用公共方法重写 Object.clone(它是受保护的)。请参阅 Object.clone(),以获得有关重写此方法的详细信息。
注意,此接口不 包含 clone 方法。因此,因为某个对象实现了此接口就克隆它是不可能的。即使 clone 方法是反射性调用的,也无法保证它将获得成功。
注意红字,也就是说,这个接口告诉计算机,这个类是可复制的。clone默认实现的是浅复制,下面就举一个利用原型模式和cloneable接口实现深复制的例子。在简历中一般包含有工作经验,我们就把它抽象出一个类。
代码实例如下:
import java.util.*; //工作经验类 class Experience implements Cloneable { private String time;//工作时间 private String where;//工作地点 //设置工作经验 public void setExperience(String time , String where) { this.time = time; this.where = where; } //显示工作经验 public String toString() { return "在"+ where + "工作过,时间为"+time+"\n"; } //克隆方法,用于深复制 protected Object clone()throws CloneNotSupportedException { return super.clone(); } } //简历类 class Resume implements Cloneable { private String name;//名字 private int age;//年龄 private Experience exp;//工作经验 //构造方法 public Resume() { this.exp = new Experience(); } //设置名字 public void setName(String name) { this.name = name; } //设置年龄 public void setAge(int age) { this.age = age; } //设置工作经验 public void setExp(String time , String where) { this.exp.setExperience(time,where); } //显示简历信息 public String toString() { return "姓名:"+this.name+" 年龄:"+ this.age+" 工作经验:"+exp.toString(); } //克隆方法 protected Object clone()throws CloneNotSupportedException { Resume obj = (Resume)super.clone(); obj.name = this.name; obj.age = age; obj.exp = (Experience)this.exp.clone(); return obj; } } public class Main { public static void main(String[] args) { try { //第一份简历 Resume r1 = new Resume(); r1.setName("Martin"); r1.setAge(23); r1.setExp("2016年","Tencent"); //第二份简历 Resume r2 = (Resume)r1.clone(); r2.setExp("2017年","Baidu"); System.out.println(r1); System.out.println(r2); }catch(CloneNotSupportedException e) { e.printStackTrace(); } } }
运行结果如下:
相关文章推荐
- C#面向对象设计模式学习笔记(5) - Prototype 原型模式(创建型模式)
- 可复用面向对象软件基础——设计模式(六)之原型模式
- 面向对象设计模式纵横谈:Prototype 原型模式(笔记记录)
- 设计模式(Design Patterns)-可复用面向对象软件的基础 05:原型模式(Prototype)和Java中的深、浅拷贝
- 一步步学习javascript基础篇(4):面向对象设计之创建对象(工厂、原型和构造函数等模式)
- C#面向对象设计模式纵横谈(6):Prototype 原型(创建型模式)
- 面向对象设计模式之Prototype原型模式(创建型)
- 面向对象设计模式之Prototype原型模式(创建型)
- [导入]C#面向对象设计模式纵横谈(6):Prototype 原型模式(创建型模式).zip(9.56 MB)
- 面向对象设计模式学习(二):Singleton单件创建型模式
- C#面向对象设计模式第一讲:面向对象设计模式与原则
- 5本最佳的Java面向对象理论和设计模式的书籍
- 黑马程序员_面向对象一(封装,构造函数,this,static,单例设计模式)
- 面向对象设计模式之Adapter适配器模式(结构型)
- C#面向对象设计模式纵横谈(四) --- Factory Method 工厂方法(创建型模式)
- [导入]C#面向对象设计模式纵横谈(5):Factory Method 工厂方法模式(创建型模式).zip(10.09 MB)
- 面向对象设计模式学习---正真的OOPL
- 面向对象设计模式学习---Singleton模式(创建型)
- 设计模式深入浅出(二)对象创建——Builder,原型,单例
- 《Head First 设计模式》代码之PHP版(面向对象学习)第1/2页