Heim  >  Artikel  >  Java  >  Master-Prototyp-Modus in fünf Minuten

Master-Prototyp-Modus in fünf Minuten

Java后端技术全栈
Java后端技术全栈nach vorne
2023-08-25 15:52:431042Durchsuche


Hallo zusammen, ich bin Lao Tian, ​​​​Heute werde ich Designmuster 原型模式 mit euch teilen. Verwenden Sie geeignete Lebensgeschichten und reale Projektszenarien, um über das Entwurfsmuster zu sprechen, und fassen Sie das Entwurfsmuster schließlich in einem Satz zusammen.

Master-Prototyp-Modus in fünf Minuten

Geschichte

Ich erinnere mich noch daran, als ich in meinem Abschlussjahr auf Jobsuche war, zufällig eine relativ schöne Lebenslaufvorlage für Programmierer aus dem Internet gefunden habe und dann die ganze Klasse angefangen hat zu kopieren ihre Lebensläufe wie verrückt (U-Disk). Gleichzeitig gab es auch einen Witz, als mehrere Studenten ihre früheren Lebensläufe kopierten, ohne den Inhalt oder ihren Namen zu ändern. Später sollte jeder das Ergebnis erraten können. Alle machten ein Praktikum, und einige von ihnen waren noch auf der Suche nach einem Job. Feedback vom Interviewer im Unternehmen und anderen Klassenkameraden später: Ich habe mehrere Lebensläufe erhalten, die genau gleich waren. Als ich zurückkam, wussten alle, wo das Problem lag, nachdem wir darüber gesprochen hatten. Ich gab zu, dass ich es kopiert und eingereicht hatte ohne es überhaupt zu ändern. Schade.

Unterteilen Sie Lebenslaufkopien in zwei Arten:

  • Eine besteht darin, den Lebenslauf zu kopieren und dann die Informationen an Ihre eigenen anzupassen.
  • Die andere besteht darin, den Lebenslauf zu kopieren, ohne den Inhalt zu ändern. „Definition von Prototypmustern“ mit Prototyp-Instanztypen und erstellen Sie neue Objekte durch Kopieren dieser Prototypen. Prototyp-Modus:
    , ein kreativer Modus.
Der Aufrufer muss weder die Erstellungsdetails kennen, noch muss er den Konstruktor aufrufen, um das Objekt zu erstellen.

Nutzungsszenarien

Der Prototyp-Modus verfügt über die folgenden Nutzungsszenarien:

  • Die Klasseninitialisierung verbraucht mehr Ressourcen
  • Ein von new generiertes Objekt erfordert einen sehr langwierigen Prozess (Datenvorbereitung, Zugriffsberechtigungen usw.)
  • Der Konstruktor ist komplizierter
  • Wenn eine große Anzahl von Objekte werden innerhalb des Schleifenkörpers generiert
  • Im Frühjahr wird häufig das Prototypmuster verwendet, zum Beispiel: scope='prototype'scope='prototype'

我们可以将一些getter和setter之类封装成一个工厂方法,然后对于使用的人来说,调用方法就可以了,不需要知道里面的getter和setter是怎么处理的。我们也可以使用JDK提供的实现Cloneable接口,实现快速复制。

创建对象的四种方式:

new、反射、克隆、序列化

实际案例

大家是否有遇到过这种常见,就是项目中规定,不能把与数据库表映射的entity类返回给前端,所以通常返回给前端的有各种O,比如:XxxVO、XxxBO、XxxDTO...

这时候就会出现下面的场景,大家也想已经猜到了。

下面是与数据库表映射的UserEntity

Wir können einige Getter und Setter in eine Factory-Methode kapseln und dann für den Benutzer einfach die Methode aufrufen, Es ist nicht erforderlich, zu wissen, wie die darin enthaltenen Getter und Setter gehandhabt werden. Wir können auch Implementierung bereitgestellt durch JDK

Vier Möglichkeiten zum Erstellen von Objekten:

new,flection, Clone, serialize🎜

Tatsächlicher Fall

🎜Jemand ist mir darauf begegnet Häufiges Problem. Im Projekt ist festgelegt, dass die der Datenbanktabelle zugeordnete Entitätsklasse nicht an das Frontend zurückgegeben werden kann. Daher werden normalerweise verschiedene O an das Frontend zurückgegeben, z. B.: XxxVO, XxxBO, XxxDTO ... 🎜 🎜Zu diesem Zeitpunkt erscheint die folgende Szene, und jeder hat es vielleicht erraten. 🎜🎜Das Folgende ist die Zuordnung zur Datenbanktabelle以下是代码的实现:

//用户地址信息
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 指向的是同一个地址。

这就是所谓的浅克隆,只是克隆了对象,对于该对象的非基本类型属性,仍指向原来对象的属性所指向的对象的内存地址。

关系如下:

Master-Prototyp-Modus in fünf Minuten


深克隆

关于深克隆,我们来用一个很经典的案例,西游记里的孙悟空。一个孙悟空能变成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

结论

深克隆后每个孙悟空都有自己的金箍棒,而浅克隆后每个孙悟空用的金箍棒实质上还是同一根。

Master-Prototyp-Modus in fünf Minuten

总结

切记:深和浅,指的是克隆对象里的属性(引用类型)是否指向同一个内存地址。

为了更深刻的理解深克隆和浅克隆,我们回答文中的简历拷贝的故事。

  • Tiefe Kopie: Kopieren Sie einen Lebenslauf und ändern Sie dann die Informationen im Lebenslauf, um ihn zu Ihrem eigenen zu machen.
  • Flache Kopie: Kopieren Sie einen Lebenslauf, und der Inhalt des Lebenslaufs bleibt völlig unverändert.

Vorteile:

  • Der Java-Prototyp-Modus basiert auf dem Kopieren von Speicher-Binärströmen, was eine bessere Leistung als direkt neu bietet.
  • Sie können Deep Cloning verwenden, um den Objektstatus zu speichern, eine alte Kopie zu speichern (klonen) und beim Ändern als Rückgängig-Funktion zu fungieren.

Nachteile:

  • Während der Transformation müssen vorhandene Klassen geändert werden, was gegen das „Öffnungs- und Schließprinzip“ verstößt.
  • Wenn es mehrere verschachtelte Referenzen zwischen Objekten gibt, muss jede Ebene geklont werden.

Wir haben eine umfassende Erklärung des Prototypmusters anhand seiner Definition, Verwendungsszenarien, realen Fälle, flachem Klonen, tiefem Klonen, Vor- und Nachteilen usw. gegeben.

Das obige ist der detaillierte Inhalt vonMaster-Prototyp-Modus in fünf Minuten. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:Java后端技术全栈. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen