Mod Prototaip Master dalam Lima Minit
Hello semua, saya Lao Tian, Hari ini saya akan berkongsi dengan anda 原型模式
dalam corak reka bentuk. Gunakan kisah hidup yang sesuai dan senario projek sebenar untuk bercakap tentang corak reka bentuk, dan akhirnya meringkaskan corak reka bentuk dalam satu ayat.
Story
Saya masih ingat ketika saya mencari pekerjaan di tahun senior saya, saya secara tidak sengaja menemui template resume pengaturcara yang agak cantik dari Internet, dan kemudian seluruh kelas mula menyalin resume gila (cakera U). Pada masa yang sama, ada juga beberapa orang pelajar menyalin resume mereka tanpa mengubah kandungan atau nama mereka. Kemudian, semua orang sepatutnya dapat meneka keputusan Semua orang pergi untuk latihan, dan sebahagian daripada mereka masih mencari pekerjaan. Maklum balas daripada penemuduga di syarikat dan rakan sekelas yang lain kemudian: Saya menerima beberapa resume yang betul-betul sama Apabila saya kembali, semua orang tahu apa masalahnya selepas kami bercakap mengenainya tanpa mengubahnya sama sekali.
Bahagikan salinan resume kepada dua jenis:
Satu adalah untuk menyalin resume dan kemudian mengubah suai maklumat kepada anda sendiri Yang lain ialah menyalin resume tanpa mengubah kandungan.
Prototype corak definisi
Menentukan jenis objek untuk membuat menggunakan contoh prototaip, dan buat objek baru dengan mengatasi prototaip ini, tentukan penciptaan objek dengan jenis contoh prototaip, dan cipta objek baharu dengan menyalin prototaip ini.Mod prototaip:
, mod kreatif.
Pemanggil tidak perlu mengetahui sebarang butiran penciptaan, dan dia juga tidak perlu memanggil pembina untuk mencipta objek.
Prototype Pattern
Senario penggunaan
Mod prototaip mempunyai senario penggunaan berikut:Pemulaan kelas menggunakan lebih banyak sumber objek dijana dalam badan gelung -
Pada Musim Bunga, corak prototaip digunakan secara meluas, contohnya:
scope='prototype'
-
Kita boleh merangkum beberapa getter dan setter ke dalam kaedah kilang, dan kemudian untuk pengguna, hanya panggil kaedah, tidak perlu Tahu bagaimana getter dan setter di dalam dikendalikan. Kita juga boleh menggunakan Pelaksanaan disediakan oleh JDK
Klon antara muka untuk mencapai penyalinan pantas. Empat cara untuk mencipta objek:
scope='prototype'
Pelaksanaan disediakan oleh JDK
Klon antara muka untuk mencapai penyalinan pantas. baharu, pantulan, Klon, serialize
Kes sebenar
UserEntityKelas entiti.
public class UserEntity { private Long id; private String name; private Integer age; //....可能还有很多属性 //省略getter setter }
public class UserVO { private Long id; private String name; private Integer age; //....可能还有很多属性 //省略getter setter }
scope='prototype'
我们可以将一些getter和setter之类封装成一个工厂方法,然后对于使用的人来说,调用方法就可以了,不需要知道里面的getter和setter是怎么处理的。我们也可以使用JDK
提供的实现Cloneable
接口,实现快速复制。
创建对象的四种方式:
new、反射、克隆、序列化
实际案例
大家是否有遇到过这种常见,就是项目中规定,不能把与数据库表映射的entity类返回给前端,所以通常返回给前端的有各种O,比如:XxxVO、XxxBO、XxxDTO...
这时候就会出现下面的场景,大家也想已经猜到了。
下面是与数据库表映射的UserEntity
Pada masa ini, UserEntity yang ditemui daripada pangkalan data perlu ditukar kepada UserVO dan kemudian dikembalikan ke bahagian hadapan (atau pemanggil).
public class ObjectConvertUtil { public static UserVo convertUserEntityToUserVO(UserEntity userEntity) { if (userEntity == null) { return null; } UserVo userVo = new UserVo(); userVo.setId(userEntity.getId()); userVo.setName(userEntity.getName()); userVo.setAge(userEntity.getAge()); //如果还有更多属性呢? return userVo; } }
从这个util类中,我们可以看出,如果一个类的属性有几十个,上百个的,这代码量是不是有点恐怖?
于是,我们通常都会使用一些工具类来处理,比如常见有以下:
BeanUtils.copy(); JSON.parseObject() Guava工具类 .....
这些工具类就用到了原型模式。
通过一个对象,创建一个新的对象。
也把原型模式称之为对象的拷贝、克隆。
其实对象的克隆分浅克隆和深克隆,下面我们就来聊聊浅克隆和深克隆。
浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原来对象的属性所指向的对象的内存地址。 深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
我们先来聊聊浅克隆,都喜欢由浅入深。
浅克隆
比如,我现在相对用户信息User进行克隆,但是User中有用户地址信息UserAddress
属性。
以下是代码的实现:
//用户地址信息 public class UserAddress implements Serializable{ private String province; private String cityCode; public UserAddress(String province, String cityCode) { this.province = province; this.cityCode = cityCode; } } //用户信息 public class User implements Cloneable { private int age; private String name; //用户地址信息 private UserAddress userAddress; //getter setter 省略 @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } //测试 public class UserTest { public static void main(String[] args) throws Exception { User user = new User(); user.setAge(20); user.setName("田维常"); UserAddress userAddress = new UserAddress("贵州", "梵净山"); user.setUserAddress(userAddress); User clone = (User) user.clone(); System.out.println("克隆前后UserAddress比较:" + (user.getUserAddress() == clone.getUserAddress())); } }
输出结果
克隆前后 UserAddress 比较:true
两个对象属性 UserAddress
指向的是同一个地址。
这就是所谓的浅克隆,只是克隆了对象,对于该对象的非基本类型属性,仍指向原来对象的属性所指向的对象的内存地址。
关系如下:
深克隆
关于深克隆,我们来用一个很经典的案例,西游记里的孙悟空。一个孙悟空能变成n多个孙悟空,手里都会拿着一个金箍棒。
按照前面的浅克隆,结果就是:孙悟空倒是变成很多孙悟空,但是金箍棒用的是同一根。
深克隆的结果是:孙悟空变成了很多个,金箍棒也变成很多个根。
下面我们用代码来实现:
//猴子,有身高体重和生日 public class Monkey { public int height; public int weight; public Date birthday; }
孙悟空也是猴子,兵器 孙悟空有个金箍棒:
import java.io.Serializable; //孙悟空的金箍棒 public class JinGuBang implements Serializable{ public float h=100; public float d=10; //金箍棒变大 public void big(){ this.h *=10; this.d *=10; } //金箍棒变小 public void small(){ this.h /=10; this.d /=10; } }
齐天大圣孙悟空:
import java.io.*; import java.util.Date; //孙悟空有七十二变,拔猴毛生成一个金箍棒 //使用JDK的克隆机制, //实现Cloneable并重写clone方法 public class QiTianDaSheng extends Monkey implements Cloneable, Serializable { public JinGuBang jinGuBang; public QiTianDaSheng() { this.birthday = new Date(); this.jinGuBang = new JinGuBang(); } @Override protected Object clone() throws CloneNotSupportedException { return this.deepClone(); } //深克隆 public QiTianDaSheng deepClone() { try { //内存中操作完成、对象读写,是通过字节码直接操作 //与序列化操作类似 ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(this); ByteArrayInputStream bais = new ByteArrayInputStream(bos.toByteArray()); ObjectInputStream bis = new ObjectInputStream(bais); //完成一个新的对象,底层是使用new创建的一个对象 //详情可以了解readObject方法 QiTianDaSheng qiTianDaSheng = (QiTianDaSheng) bis.readObject(); //每个猴子的生日不一样,所以每次拷贝的时候,把生日改一下 qiTianDaSheng.birthday = new Date(); return qiTianDaSheng; } catch (Exception ex) { ex.printStackTrace(); return null; } } //浅克隆,就是简单的赋值 public QiTianDaSheng shalllowClone(QiTianDaSheng target) { QiTianDaSheng qiTianDaSheng = new QiTianDaSheng(); qiTianDaSheng.height = target.height; qiTianDaSheng.weight = target.weight; qiTianDaSheng.jinGuBang = target.jinGuBang; qiTianDaSheng.birthday = new Date(); return qiTianDaSheng; } }
接着我们就来测试一下:
public class DeepCloneTest { public static void main(String[] args) { QiTianDaSheng qiTianDaSheng = new QiTianDaSheng(); try { QiTianDaSheng newObject = (QiTianDaSheng) qiTianDaSheng.clone(); System.out.print("深克隆后 "); System.out.println("金箍棒是否一直:" + (qiTianDaSheng.jinGuBang == newObject.jinGuBang)); } catch (Exception ex) { ex.printStackTrace(); } QiTianDaSheng newObject=qiTianDaSheng.shalllowClone(qiTianDaSheng); System.out.print("浅克隆后 "); System.out.println("金箍棒是否一直:" + (qiTianDaSheng.jinGuBang == newObject.jinGuBang)); } }
输出结果为:
深克隆后 金箍棒是否一直:false 浅克隆后 金箍棒是否一直:true
结论
深克隆后每个孙悟空都有自己的金箍棒,而浅克隆后每个孙悟空用的金箍棒实质上还是同一根。
总结
切记:深和浅,指的是克隆对象里的属性(引用类型)是否指向同一个内存地址。
为了更深刻的理解深克隆和浅克隆,我们回答文中的简历拷贝的故事。
Salinan dalam: Salin resume, dan kemudian ubah suai maklumat dalam resume untuk menjadikannya milik anda Salinan cetek: Salin resume, dan kandungan resume kekal tidak berubah sepenuhnya
Kelebihan
-
Mod prototaip Java adalah berdasarkan salinan strim binari memori, yang mempunyai prestasi yang lebih baik daripada baharu langsung. Anda boleh menggunakan pengklonan dalam untuk menyimpan keadaan objek, menyimpan salinan lama (mengklonkannya), dan apabila mengubah suainya, ia boleh bertindak sebagai fungsi buat asal.
Kelemahan:
perlu mengkonfigurasi kaedah klon, dan kelas sedia ada perlu diubah suai semasa transformasi, yang melanggar "prinsip pembukaan dan penutupan". Jika terdapat berbilang rujukan bersarang antara objek, setiap lapisan perlu diklon.
Kami telah memberikan penjelasan menyeluruh tentang corak prototaip dari definisinya, senario penggunaan, kes sebenar, pengklonan cetek, pengklonan dalam, kelebihan dan kekurangan, dsb.
Atas ialah kandungan terperinci Mod Prototaip Master dalam Lima Minit. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

Video Face Swap
Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas

Panduan Nombor Sempurna di Jawa. Di sini kita membincangkan Definisi, Bagaimana untuk menyemak nombor Perfect dalam Java?, contoh dengan pelaksanaan kod.

Panduan untuk Weka di Jawa. Di sini kita membincangkan Pengenalan, cara menggunakan weka java, jenis platform, dan kelebihan dengan contoh.

Panduan untuk Nombor Smith di Jawa. Di sini kita membincangkan Definisi, Bagaimana untuk menyemak nombor smith di Jawa? contoh dengan pelaksanaan kod.

Dalam artikel ini, kami telah menyimpan Soalan Temuduga Spring Java yang paling banyak ditanya dengan jawapan terperinci mereka. Supaya anda boleh memecahkan temuduga.

Java 8 memperkenalkan API Stream, menyediakan cara yang kuat dan ekspresif untuk memproses koleksi data. Walau bagaimanapun, soalan biasa apabila menggunakan aliran adalah: bagaimana untuk memecahkan atau kembali dari operasi foreach? Gelung tradisional membolehkan gangguan awal atau pulangan, tetapi kaedah Foreach Stream tidak menyokong secara langsung kaedah ini. Artikel ini akan menerangkan sebab -sebab dan meneroka kaedah alternatif untuk melaksanakan penamatan pramatang dalam sistem pemprosesan aliran. Bacaan Lanjut: Penambahbaikan API Java Stream Memahami aliran aliran Kaedah Foreach adalah operasi terminal yang melakukan satu operasi pada setiap elemen dalam aliran. Niat reka bentuknya adalah

Panduan untuk TimeStamp to Date di Java. Di sini kita juga membincangkan pengenalan dan cara menukar cap waktu kepada tarikh dalam java bersama-sama dengan contoh.

Kapsul adalah angka geometri tiga dimensi, terdiri daripada silinder dan hemisfera di kedua-dua hujungnya. Jumlah kapsul boleh dikira dengan menambahkan isipadu silinder dan jumlah hemisfera di kedua -dua hujungnya. Tutorial ini akan membincangkan cara mengira jumlah kapsul yang diberikan dalam Java menggunakan kaedah yang berbeza. Formula volum kapsul Formula untuk jumlah kapsul adalah seperti berikut: Kelantangan kapsul = isipadu isipadu silinder Dua jumlah hemisfera dalam, R: Radius hemisfera. H: Ketinggian silinder (tidak termasuk hemisfera). Contoh 1 masukkan Jejari = 5 unit Ketinggian = 10 unit Output Jilid = 1570.8 Unit padu menjelaskan Kirakan kelantangan menggunakan formula: Kelantangan = π × r2 × h (4

Java ialah bahasa pengaturcaraan popular yang boleh dipelajari oleh pembangun pemula dan berpengalaman. Tutorial ini bermula dengan konsep asas dan diteruskan melalui topik lanjutan. Selepas memasang Kit Pembangunan Java, anda boleh berlatih pengaturcaraan dengan mencipta program "Hello, World!" Selepas anda memahami kod, gunakan gesaan arahan untuk menyusun dan menjalankan program, dan "Hello, World!" Pembelajaran Java memulakan perjalanan pengaturcaraan anda, dan apabila penguasaan anda semakin mendalam, anda boleh mencipta aplikasi yang lebih kompleks.
