创建型模式之原型模式(2.3)
程序员文章站
2022-03-20 22:05:28
简单来说,通过复制的方式创建对象。
【举个栗子】:点外卖的收货地址
......
什么是原型模式?
简单来说,通过复制的方式创建对象。(被复制的对象可以理解为模板)
原型模式的应用场景
复杂结构对象的创建。
复杂结构对象:可以理解为对象里面还有对象。
【举个栗子】:点外卖的收货地址
收货地址包括姓名,电话和住址。第一次点外卖的时候需要完整的填写这些信息,但是之后点的过程基本上是不用再重新填写这些信息的。试想一下,每次下单之前都要填一遍姓名,电话,详细地址(假设省市已经定位好了)。头大.....而这个场景,正是原型模式的用武之地。
点外卖之前复制上一次填写的地址,直接下单;或者手机号出现变更,修改一下直接更新到模板即可。
原型模式的本质是创建一个对象模板,然后通过复制的方式实现复用。
深拷贝(复杂对象一波带走)
在深拷贝之前,简单聊一下浅拷贝。
以上述收货地址为例,如果只涉及到姓名,电话这些基本数据类型(浅拷贝与深拷贝是基本没有区别的),但是如果涉及到地址这样的引用类型。浅拷贝就会出现问题。浅拷贝对于引用对象,只复制其引用地址。所以复制出来的对象和被复制的对象会指向同一个值。假设你想建立两个收货模板,地址是不同的,那么就只能使用深拷贝了。
撸段代码试试看:
思路:
1.创建info类和address类继承serializable接口,为了后面实现序列化写入内存。(实现平台无关性)
2.info类还需要继承cloneable接口,并重写clone()方法,注:protected改为public
3.在clone()方法中添加写入内存和读取的逻辑
4.info info1 = (info) info.clone();创建对象,并可做灵活修改。
import java.io.*; class address implements serializable { private string province; private string city; private string street; private string door_number; public address(string province, string city, string street, string door_number) { this.province = province; this.city = city; street = street; this.door_number = door_number; } public string getprovince() { return province; } public void setprovince(string province) { this.province = province; } public string getcity() { return city; } public void setcity(string city) { this.city = city; } public string getstreet() { return street; } public void setstreet(string street) { street = street; } public string getdoor_number() { return door_number; } public void setdoor_number(string door_number) { this.door_number = door_number; } @override public string tostring() { return "address{" + "province='" + province + '\'' + ", city='" + city + '\'' + ", street='" + street + '\'' + ", door_number='" + door_number + '\'' + '}'; } } class info implements cloneable, serializable //1.创建一个外卖信息类,继承cloneable(可复制),serializable(可序列化) { private string name; private string number; address address; public string getname() { return name; } public void setname(string name) { this.name = name; } public string getnumber() { return number; } public void setnumber(string number) { this.number = number; } public address getaddress() { return address; } public void setaddress(address address) { this.address = address; } public info(string name, string number, address address) { this.name = name; this.number = number; this.address = address; } @override public string tostring() { return "info{" + "name='" + name + '\'' + ", number='" + number + '\'' + ", address=" + address + '}'; } @override public object clone() throws clonenotsupportedexception { //2.重写clone方法,并把protected换成public bytearrayoutputstream out = new bytearrayoutputstream(); try { objectoutputstream oos = new objectoutputstream(out); oos.writeobject(this); //写入内存 oos.close(); byte[] bytes = out.tobytearray(); inputstream in = new bytearrayinputstream(bytes); objectinputstream ois = new objectinputstream(in); object clone = ois.readobject(); //读取内存 ois.close(); return clone; } catch (exception e) { throw new runtimeexception(e); } } } /* clone()方法直接复制在内存中已经创建对象的二进制,效率极高!(不需要调用构造器) protected native object clone() throws clonenotsupportedexception; native修饰的方法直接调用底层的c语言 */ public class myinfo { public static void main(string[] args) throws clonenotsupportedexception { info info = new info("shadow","18116207310",new address("上海","浦东新区","振南路","355")); system.out.println(info); info info1 = (info) info.clone(); //3.复制加强转 system.out.println(info1); system.out.println("//修改电话:"); info info2 = (info) info.clone(); info2.setnumber("123456789"); system.out.println(info2); system.out.println("//修改地址:"); info info3 = (info) info.clone(); info3.getaddress().setstreet("西语街"); info3.getaddress().setdoor_number("666"); system.out.println(info3); } }
输出结果: