Patrones de diseño detallados: patrones prototipo

Este artículo echa un vistazo al cuarto modo en el modo de creación: el modo prototipo. Todavía queda mirar primero las dos imágenes, revisar el tipo de modo y profundizar en la memoria.

definición:

Modo de prototipo: use una instancia de prototipo para especificar el tipo de objeto que se creará y cree un nuevo objeto copiando este prototipo .

Patrón de prototipo: especifique los tipos de objetos para crear utilizando una instancia prototípica y cree nuevos objetos copiando este prototipo .

  1. Cómo funciona: Pase un objeto prototipo al objeto que se creará (es decir, el objeto del cliente), y el objeto que se creará implementará el proceso de creación solicitando al objeto prototipo que se copie a sí mismo.
  2. La fábrica para crear nuevos objetos (también conocidos como objetos clonados) es la propia clase prototipo, y el método de fábrica es implementado por el método clon responsable de copiar el objeto prototipo.
  3. Los objetos creados por el método de clonación son objetos completamente nuevos , tienen nuevas direcciones en la memoria y cada objeto clonado es independiente.
  4. Después de modificar el objeto clonado de diferentes maneras, se pueden obtener una serie de objetos similares pero no idénticos.

analizar:

Sun Wukong: copia (clona) varios cuerpos según su propia forma

Desarrollo de software: obtenga múltiples objetos nuevos que sean exactamente iguales al objeto prototipo copiando un objeto prototipo

estructura:

El patrón Prototype contiene los siguientes 3 roles:

Prototipo (clase de prototipo abstracto)

ConcretePrototype (clase de prototipo de hormigón)

Cliente (clase de cliente)

Diagrama de clase:

Clasificación:

Clon superficial : cuando se copia el objeto prototipo, solo se copian él mismo y las variables miembro del tipo de valor que contiene, mientras que las variables miembro del tipo de referencia no se copian.

Deep Clone : ​​Además de copiar el objeto en sí, también se copiarán todas las variables miembro contenidas en el objeto.

Gerente de prototipos:

El administrador de prototipos (Prototype Manager) almacena múltiples objetos prototipo en una colección para que los use el cliente. Es una fábrica responsable de la clonación de objetos , que define una colección para almacenar objetos prototipo. Si se requiere un objeto prototipo. Un clon, que puede ser obtenido copiando el objeto prototipo correspondiente en la colección

aplicabilidad:

El costo de crear un nuevo objeto es alto , y el nuevo objeto se puede obtener copiando el objeto existente.Si es un objeto similar, sus variables miembro se pueden modificar ligeramente.

El sistema quiere guardar el estado del objeto, y el estado del objeto cambia muy poco.

Es necesario evitar el uso de clases de fábrica jerárquicas para crear objetos jerárquicos , y el objeto de instancia de la clase tiene solo uno o algunos estados combinados. Puede ser más conveniente obtener una nueva instancia copiando el objeto prototipo que usar el constructor. para crear una nueva instancia

ventaja:

Simplifique el proceso de creación de objetos y mejore la eficiencia de crear nuevas instancias copiando una instancia existente

Buena escalabilidad

Se proporciona una estructura de creación simplificada.La copia de productos en el modo de prototipo se realiza a través del método de clonación encapsulado en la clase de prototipo, y no hay necesidad de una clase de fábrica especial para crear productos.

Puede usar la clonación profunda para guardar el estado del objeto para que pueda usarse cuando sea necesario, lo que puede ayudar en la implementación de operaciones de deshacer

defecto:

Cada clase debe estar equipada con un método de clonación , y el método de clonación se encuentra dentro de una clase. Al modificar una clase existente, el código fuente debe modificarse, lo que viola el principio de apertura y cierre.

Al implementar la clonación profunda, es necesario escribir código más complejo , y cuando hay múltiples referencias anidadas entre objetos, para implementar la clonación profunda, la clase correspondiente a cada capa de objetos debe admitir la clonación profunda, lo que puede ser problemático de implementar.


Caso 1: (código .NET)

Programa.cs

using System;

namespace PrototypeSample
{
    class Program
    {
        static void Main(string[] args)
        {
            /*
            ConcretePrototypeB prototype, copy;
            prototype = new ConcretePrototypeB();
            //prototype.Attr = "Sunny";
            copy = (ConcretePrototypeB)prototype.Clone();
            //copy.Attr = "Tom";
            Console.WriteLine(prototype == copy);
            //Console.WriteLine(prototype.GetType() == copy.GetType());
            Console.WriteLine(prototype.Member == copy.Member);
            Console.Read();
            */

            WeeklyLog log_previous, log_new;
            log_previous = new WeeklyLog();
            Attachment attachment = new Attachment();
            log_previous.Attachment = attachment;
            log_new = log_previous.Clone();
            Console.WriteLine("周报是否相同?{0}",(log_previous == log_new)?"是":"否");
            Console.WriteLine("附件是否相同?{0}",(log_previous.Attachment == log_new.Attachment)?"是":"否");
            Console.Read();
        }
    }
}

Adjunto.cs

using System;

namespace PrototypeSample
{
    [Serializable]
    class Attachment
    {
        private string name;

        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        public void Download()
        {
            Console.WriteLine("下载附件,文件名为{0}。",name);
        }
    }
}

WeekLog.cs

using System;
using System.IO;
using System.Collections;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;

namespace PrototypeSample
{
    [Serializable]
    class WeeklyLog
    {
        private Attachment attachment;
        private string name;
        private string date;     
        private string content;

        public Attachment Attachment
        {
            get { return attachment; }
            set { attachment = value; }
        }

        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        public string Date
        {
            get { return date; }
            set { date = value; }
        }

        public string Content
        {
            get { return content; }
            set { content = value; }
        }

        /*
        //使用MemberwiseClone()方法实现浅克隆
        public WeeklyLog Clone()
        {
            return this.MemberwiseClone() as WeeklyLog;
        }
         */

        //使用序列化方式实现深克隆
        public WeeklyLog Clone()
        {
            WeeklyLog clone = null;
            FileStream fs = new FileStream("Temp.dat", FileMode.Create);
            BinaryFormatter formatter = new BinaryFormatter();
            try
            {
                formatter.Serialize(fs, this);
            }
            catch (SerializationException e)
            {
                Console.WriteLine("Failed to serialize. Reason: " + e.Message);
                throw;
            }
            finally
            {
                fs.Close();
            }

            FileStream fs1 = new FileStream("Temp.dat", FileMode.Open);
            BinaryFormatter formatter1 = new BinaryFormatter();
            try
            {
                clone = (WeeklyLog)formatter1.Deserialize(fs1);
            }
            catch (SerializationException e)
            {
                Console.WriteLine("Failed to deserialize. Reason: " + e.Message);
                throw;
            }
            finally
            {
                fs.Close();
            }
            return clone;
        }
    }
}

Demo.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PrototypeSample
{
    abstract class Prototype
    {
        public abstract Prototype Clone();
    }

    class ConcretePrototype : Prototype
    {
        private Member member;

        public Member Member
        {
            get { return member; }
            set { member = value; }
        }

        private string attr; //成员变量

        public string Attr
        {
            get { return attr; }
            set { attr = value; }
        }

        //克隆方法
        public override Prototype Clone()
        {
            ConcretePrototype prototype = new ConcretePrototype();
            //prototype.Attr = this.Attr;
            //this.Attr = "Sunny";
            //prototype.Attr = new String(this.Attr.ToCharArray());
            //prototype.Member = this.Member;
            prototype.Member = new Member();
            return prototype;
        }
    }
}

Demo_CS.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PrototypeSample
{
    class Member
    {

    }

    class ConcretePrototypeA
    {
        private Member member;

        public Member Member
        {
            get { return member; }
            set { member = value; }
        }

        private string attr; //成员变量

        public string Attr
        {
            get { return attr; }
            set { attr = value; }
        }

        //克隆方法
        public ConcretePrototypeA Clone()
        {
            return (ConcretePrototypeA)this.MemberwiseClone();
        }
    }

    class ConcretePrototypeB : ICloneable
    {
        private Member member;

        public Member Member
        {
            get { return member; }
            set { member = value; }
        }

        public object Clone()
        {
            ConcretePrototypeB copy = (ConcretePrototypeB)this.MemberwiseClone();
            Member newMember = new Member();
            copy.Member = newMember;
            return copy;
        }
    }
}

Caso 2: (código JAVA)

    1. Prototype
       declara una interfaz que se clona a sí misma.

    2. ConcretePrototype
       implementa una operación de clonación de sí mismo.

    3. El cliente
       permite que un prototipo se anule * a sí mismo para crear un nuevo objeto.

Prototipo

public class Prototype implements Cloneable {

    private String name;
    
    public void setName(String name) {
        this.name = name;
    }
    
    public String getName() {
        return this.name;
    }

    public Object clone(){
        try {
            return super.clone();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

HormigónPrototipo

public class ConcretePrototype extends Prototype {

    public ConcretePrototype(String name) {
        setName(name);
    }
}

Cliente

public class Test {

    public static void main(String[] args) {
        Prototype pro = new ConcretePrototy*e("prototype");
        Prototype pro2 = (Prototype)pro.clone();
        System.out.println(pro.getName());
        System.out.println(pro2.getName());
    }
}

Supongo que te gusta

Origin blog.csdn.net/daobaqin/article/details/127740230
Recomendado
Clasificación