设计模式之原型模式

来源:互联网 发布:单例模式 js 编辑:程序博客网 时间:2024/05/22 03:34

在GOF对原型模式的定义是:用原型模式指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

所谓的原型模式其实就是依托一个已经实例化的对象去创建另外一个可以进行定制的对象,而不需要知道创建过程中的具体细节。原型模式的基本代码如下:

/** *  * @author ricardo * @Time 上午11:47:45 * @Function:抽象原型类 * */public abstract class Prototype {private String id;public Prototype(String id) {this.id = id;}public String getId() {return this.id;}public abstract Prototype Clone();}
/** *  * @author ricardo * @Time 上午11:48:21 * @Function:具体原型类 * */public class ConcretePrototype extends Prototype{public ConcretePrototype(String id) {super(id);}@Overridepublic Prototype Clone() {ConcretePrototype con = new ConcretePrototype(this.getId());return con;}}

客户端代码:

public class Celnet {public static void main(String[] args) {ConcretePrototype concretePrototype1 = new ConcretePrototype("测试数据ID");ConcretePrototype concretePrototype12 = (ConcretePrototype)concretePrototype1.Clone();System.out.println(concretePrototype12.getId());}}
运行截图:


举个例子,报名去考证需要录入报名信息,小青现在要报考软件设计师和系统集成项目管理工程师,报名信息差不多,但是小青想,能不能用原型模式来只需要创建一次报名信息呢?这样如果以后还要考证,就不需要再录入信息了。代码如下:

/** *  * @author ricardo * @Time 上午11:51:15 * @Function:报名信息类 * */public class RestrationInfo implements Cloneable {private String name;private String birthday;private String school;private String ID;public RestrationInfo(String name) {this.name = name;}public void setName(String name) {this.name = name;}public void setBirthday(String birthday) {this.birthday = birthday;}public void setSchool(String school) {this.school = school;}public void setID(String iD) {ID = iD;}public void Show() {System.out.println("姓名:" + name);System.out.println("学校:" + school);System.out.println("生日:" + birthday);System.out.println("身份证号:" + ID);}@Overrideprotected Object clone() {try {return super.clone();} catch (CloneNotSupportedException e) {return null;}}}
Java提供给我们一个clone的接口,实现他就能实现复制对象,客户端代码如下:

public class Celnet {public static void main(String[] args) {System.out.println("小青报名软件工程师考试");RestrationInfo info = new RestrationInfo("小青");info.setBirthday("1995年12月12日");info.setID("1234656987562");info.setSchool("史莱姆学院");info.Show();System.out.println("小青要报考系统集成项目管理工程师");RestrationInfo info2 = (RestrationInfo)info.clone();info2.Show();}}
运行截图:



看上去实现功能是很OK的,但是事实上并不是我们想象的那样nice,比如,小青现在把国籍也放到了报名信息里面,但是是新建了一个国籍的Object

/** *  * @author ricardo * @Time 下午12:43:57 * @Function:国籍信息 * */public class Nationality {private String nation;public Nationality(String nation) {super();this.nation = nation;}public Nationality() {super();}public String getNation() {return nation;}public void setNation(String nation) {this.nation = nation;}}

将国籍添加到报名信息中

/** *  * @author ricardo * @Time 上午11:51:15 * @Function:报名信息类 * */public class RestrationInfo implements Cloneable {private String name;private String birthday;private String school;private String ID;private Nationality nation;public RestrationInfo(String name) {this.name = name;nation = new Nationality();}public void setName(String name) {this.name = name;}public void setBirthday(String birthday) {this.birthday = birthday;}public void setSchool(String school) {this.school = school;}public void setID(String iD) {ID = iD;}public void Show() {System.out.println("姓名:" + name);System.out.println("学校:" + school);System.out.println("生日:" + birthday);System.out.println("身份证号:" + ID);System.out.println("国籍信息:" + nation.getNation());}@Overrideprotected Object clone() {try {return super.clone();} catch (CloneNotSupportedException e) {return null;}}}
运行截图:


可以看到,引用类型的数据,会被一起复制过来,这也是经常需要警惕的,是、值与引用的区别所在了。

那么我们需要做的,就是给国籍这个Object实现克隆接口

/** *  * @author ricardo * @Time 下午12:43:57 * @Function:国籍信息 * */public class Nationality implements Cloneable{private String nation;public Nationality(String nation) {super();this.nation = nation;}public Nationality() {super();}public String getNation() {return nation;}public void setNation(String nation) {this.nation = nation;}@Overrideprotected Object clone() {// TODO Auto-generated method stubtry {return super.clone();} catch (CloneNotSupportedException e) {// TODO Auto-generated catch blockreturn null;}}}
/** *  * @author ricardo * @Time 上午11:51:15 * @Function:报名信息类 * */public class RestrationInfo implements Cloneable {private String name;private String birthday;private String school;private String ID;private Nationality nation;public RestrationInfo(String name) {this.name = name;nation = new Nationality();}private RestrationInfo(Nationality nation) {this.nation = (Nationality) nation.clone();}public void setNationality(String nationality) {nation.setNation(nationality);}public void setName(String name) {this.name = name;}public void setBirthday(String birthday) {this.birthday = birthday;}public void setSchool(String school) {this.school = school;}public void setID(String iD) {ID = iD;}public void Show() {System.out.println("姓名:" + name);System.out.println("学校:" + school);System.out.println("生日:" + birthday);System.out.println("身份证号:" + ID);System.out.println("国籍信息:" + nation.getNation());}@Overrideprotected Object clone() {RestrationInfo obj = new RestrationInfo(this.nation);obj.name = this.name;obj.birthday = this.birthday;obj.ID = this.ID;obj.school = this.school;return obj;}}
客户端运行截图


原型模式也同样隐藏了对象的实现细节,通过该模式,类的使用者可以复制一个对象实例来创建新对象。通过复制对象实例来创建新的对象和调用构造方法来创建新对象的区别在于,复制的对象一般都会包括原有对象的状态信息。

以上内容,整理自刘径舟,张玉华编著的《设计模式其实很简单》读书笔记,欢迎转载







原创粉丝点击