参考:原型模式 | 菜鸟教程
首先一点,原型模式是用来创建对象的,只不过不是使用new关键字来创建对象,也不是使用工厂模式的静态方法创建,而是使用clone关键字。
使用new关键字创建的对象,以及使用工厂方法创建的对象,每一个对象创建完成后,这个对象都是新的,这个“新”是指,没有进行过加工。
原型模式创建对象时,是依靠一个已存在的对象,通过拷贝(克隆)这个已存在的对象的方式来创建对象。这个已存在对象,也许是刚创建的全新的对象,也可能是进行了很多操作的对象(经过加工的对象),比如设置了某些属性值之后的对象。
举个例子:期末考试之后发成绩通知书,每个学生发一张通知书,通知书上需要填写学生的年级、班级、姓名、总评。可以有两种方式:
方式1(工厂模式):拿出一张空白的通知书(new一个stu对象),设置这个stu对象的年级、班级、姓名、总评,每个学生都要执行这个操作。这个过程存在一个可以优化的点,因为都是一个班级的同学,那么,年级和班级肯定是一样的吧,如果每次都设置新的stu对象的年级、班级,那么这个操作就有点多余了,因为这个统一设置一次就OK了。
方式2(原型模式):拿出一张空白的通知书(new一个stu对象),把这张通知书上的年级、班级先写好,然后,复印很多张出来,然后,对于每一张通知书,单独填写姓名和总评。
使用普通方法(方式1)来实现:
<?php
class Student {
private $grade;
private $class;
private $name;
private $score;
public function setGrade($grade) {
$this->grade = $grade;
}
public function setClass($class) {
$this->class = $class;
}
public function setName($name) {
$this->name = $name;
}
public function setScore($score) {
$this->score = $score;
}
public function showInformation() {
echo $this->grade, " ", $this->class, " ", $this->name, " ", $this->score, "
";
}
}
//第一个学生
$stu1 = new Student();
$stu1->setGrade("大一");
$stu1->setClass("四班");
$stu1->setName("张三");
$stu1->setScore(99);
$stu1->showInformation();
//第二个学生
$stu2 = new Student();
$stu2->setGrade("大一");
$stu2->setClass("四班");
$stu2->setName("李四");
$stu2->setScore(100);
$stu2->showInformation();
使用原型模式——PHP实现
<?php
class Student {
private $grade;
private $class;
private $name;
private $score;
public function setGrade($grade) {
$this->grade = $grade;
}
public function setClass($class) {
$this->class = $class;
}
public function setName($name) {
$this->name = $name;
}
public function setScore($score) {
$this->score = $score;
}
public function showInformation() {
echo $this->grade, " ", $this->class, " ", $this->name, " ", $this->score, "
";
}
}
//创建一个原型
$prototype = new Student();
$prototype->setGrade("大一");
$prototype->setClass("四班");
//克隆原型,创建第一名同学
$stu1 = clone $prototype;
$stu1->setName("张三");
$stu1->setScore("99");
$stu1->showInformation();
//克隆原型,创建第二名同学
$stu2 = clone $prototype;
$stu2->setName("张三");
$stu2->setScore("99");
$stu2->showInformation();
使用原型模式——Java实现
// 实现Cloneable接口
class Student implements Cloneable{
private String grade;
private String _class;
private String name;
private double score;
public void setGrade(String grade) {
this.grade = grade;
}
public void setClass(String _class) {
this._class = _class;
}
public void setName(String name) {
this.name = name;
}
public void setScore(double score) {
this.score = score;
}
public void showInformation() {
System.out.println(
"grade: " + this.grade + "
" +
"class: " + this._class + "
" +
"name : " + this.name +"
" +
"score: " + this.score + "
"
);
}
// 通过调用super.clone()来实现clone方法
public Student clone() throws CloneNotSupportedException {
return (Student)super.clone();
}
}
public class Test{
public static void main(String[] args) throws Exception{
// 创建一个原型
Student prototype = new Student();
prototype.setGrade("freshman");
prototype.setClass("four");
//克隆原型,创建第一名同学
Student stu1 = prototype.clone();
stu1.setName("LiMing");
stu1.setScore(99);
//克隆原型,创建第二名同学
Student stu2 = prototype.clone();
stu2.setName("LiBai");
stu2.setScore(60);
stu1.showInformation();
// grade: freshman
// class: four
// name : LiMing
// score: 99.0
stu2.showInformation();
// grade: freshman
// class: four
// name : LiBai
// score: 60.0
stu1.showInformation();
// grade: freshman
// class: four
// name : LiMing
// score: 99.0
}
}