首页 > 其他分享 >看完这篇原型设计模式,还不会,请你吃瓜

看完这篇原型设计模式,还不会,请你吃瓜

时间:2023-02-20 08:44:04浏览次数:34  
标签:Console Name 这篇 Teacher 原型 WriteLine MyStudent 设计模式 public

概述

使用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

在软件系统开发中,有时候会遇到这样的情况:我们需要用到多个相同实例,最简单直接的方法是通过多次调用new方法来创建相同的实例。

student s=new student();
student s1=new student();
student s2=new student();

但是有一个问题,如果我用要使用的实例创建起来十分耗费资源,或者创建起来步骤比较繁琐,上边的代码缺点就暴露出来了:耗费资源,每次创建实例都要重复繁琐的创建过程。原始模式可以很好地解决这个问题,使用原型模式我们不需要每次都new一个新的实例,而是通过拷贝原有的对象来完成创建,这样我们就不需要在内存中创建多个对象,也不需要重复复杂的创建过程了。下边以克隆学生为例解释原型模式的用法,代码非常简单。

C#通过this.MemberwiseClone()实现原型模式

    /// <summary>
    /// //原型抽象类
    /// </summary>
    public abstract class StudentPrototype
    {
        public string  Name { get;  }
        public StudentPrototype(string name)
        {
            Name=name;
        }
        public  abstract StudentPrototype Clone();
    }
    /// <summary>
    /// 学生类继承原型抽象类 并重写Clone();
    /// </summary>
    public class Student : StudentPrototype
    {
        public Student(string name) : base(name)
        {
        }

        public override StudentPrototype Clone()
        {
            //浅拷贝
            //值类型成员:全都复制一份,并且搞一份新的。
            //引用类型:只是复制其引用,并不复制其对象。
            return (StudentPrototype)this.MemberwiseClone();
        }
    }
Console.WriteLine("原型设计模式");
Student student=new Student("mhg");
Student student1=(Student)student.Clone();
Console.WriteLine(student.GetHashCode());
Console.WriteLine(student1.GetHashCode());
Console.WriteLine(student1.Name);

结论:实现该原型模式,第一需要定义一个抽象类,定义一个抽象方法;第二写一个类继承该抽象类。重写抽象方法即可。重写抽象方法的逻辑使用this.MemberwiseClone();

C#自己继承ICloneable实现原型模式

  public class Teacher:ICloneable
    {
        public Teacher(string name)
        {
            Name=name;
        }
        public string Name { get; }

        public object Clone()
        {
           return this.MemberwiseClone();   
        }
    }
Console.WriteLine("C#自己继承ICloneable");
Teacher teacher=new Teacher("mhg2");
Teacher teacher2=(Teacher)teacher.Clone();

  Console.WriteLine(teacher.GetHashCode());
  Console.WriteLine(teacher2.GetHashCode());
  Console.WriteLine(teacher2.Name);

结论:定义一个类继承ICloneable,然后使用this.MemberwiseClone()实现,这种方式更简单。

这里需要注意一点:通过this.MemberWiseClone()获取一个对象的实例属于浅拷贝,对实例的简单类型属性进行全值拷贝(包含string类型),对复杂类型属性只拷贝了引用。

下面咱们验证一下浅拷贝确实只对值类型成员全部复制了一份,搞成了一份新的,对于引用类型,只是复制了其引用,并不复制其对象。

我们还是继续用Teacher这个类,在这个类里面增加一个引用类型MyStudent,咱上代码。

    public class Teacher : ICloneable
    {
        public string? Name { get; set; }
        public MyStudent? MyStudent { get; set; }
        public object Clone()
        {
            return this.MemberwiseClone();
        }
        public void Show()
        {
            Console.WriteLine($"Teacher:{Name}");
            Console.WriteLine($"MyStudent name:{MyStudent.Name}");
            Console.WriteLine($"MyStudent Age:{MyStudent.Age}");
        }
    }
   
    public class MyStudent
    {
        public string Name { get; set; }
        public string  Age { get; set; }
    }

看下执行结果

通过执行克隆了一份新对象,修改了Teacher.Mystudent.Name和Teacher.Mystudent.Age的值,其teacher对象Mystudent.Name和MyStudent.Age值也会发生变化,而修改了Teacher2.Name的值,其teacher对象的name却没有发生变化。也就验证我们上面所说的,原型浅拷贝关于值类型全部复制一份,对于引用只复制其引用,这点特别重要,很多人搞不明白,多动手实践一下。

那如果就上面的问题而言,我们现在既想对原型里面的值类型复制一份新的,也想把引用类型复制一份新的对象,并不仅仅只是再复制其引用,该怎么实现呢?

通过原型伪深拷贝实现

    public class Teacher : ICloneable
    {
        public string? Name { get; set; }
        public MyStudent? MyStudent { get; set; }
        public Teacher()
        {
            MyStudent=new MyStudent();    
        }
        private Teacher(MyStudent myStudent)
        {
            MyStudent=(MyStudent)myStudent.Clone();
        }
        public object Clone()
        {            
            //在创建新对象的时候把工作经验这个引用类型也复制一份
            Teacher teacher1 = new Teacher(MyStudent)
            {
                Name = Name
            };
            return teacher1;

            //如果依然调用this.MemberwiseClone();引用类型,就永远不可能被复制一份新的
            //return this.MemberwiseClone(); //这种写法只能拷贝值类型

        }
        public void Show(string objectName)
        {
            Console.WriteLine($"-------------{objectName}-start----------------");
            Console.WriteLine($"{objectName}:{Name}");
            Console.WriteLine($"MyStudent-name:{MyStudent.Name}");
            Console.WriteLine($"MyStudent-Age:{MyStudent.Age}");
            Console.WriteLine($"-------------{objectName}-end----------------\r\n");
        }
    }
   
    public class MyStudent:ICloneable
    {
        public string Name { get; set; }
        public string  Age { get; set; }

        public object Clone()
        {
            return this.MemberwiseClone();
        }
    }

来看看执行结果

通过上述代码运行可以看出,teacher1、teacher2、teacher3几个对象的创建...最后不仅把值类型全部复制了一份新的,引用类型也复制了一份对象,不再是复制其引用了。

目前这种原型创建还只是伪深拷贝,如果在MyStudent类中在出现一个引用类型,那么就需要使用递归。这种方式显而易见是有问题的,如果要真正的实现深拷贝,需要通过反射和序列化来实现.

总结

上述案例我们分别讲了原型浅拷贝,原型伪深拷贝,如何实现真正的深拷贝,其实也很简单,这次就不再往下写了,文章写短了没人看,写长了更没人看!关于案例中的其他问题,有疑问,欢迎交流!

 

标签:Console,Name,这篇,Teacher,原型,WriteLine,MyStudent,设计模式,public
From: https://www.cnblogs.com/mhg215/p/17127080.html

相关文章

  • 设计模式(十)----结构型模式之适配器模式
    1、概述如果去欧洲国家去旅游的话,他们的插座如下图最左边,是欧洲标准。而我们使用的插头如下图最右边的。因此我们的笔记本电脑,手机在当地不能直接充电。所以就需要一个插......
  • 设计模式之观察者模式
    spring的观察者模式demo1.观察者模式与发布与订阅模式对比:观察者模式比较概念的解释是,目标和观察者是基类,目标提供维护观察者的一系列方法,观察者提供更新接口。具体观察......
  • 设计模式入门
    1、简介  设计模式(Designpattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这......
  • 设计模式-简单工厂
    api.h#pragmaonce#include<string>#include<iostream>classAPI{public: virtualvoidrun(std::string)=0;protected: API(){};};classBAPI:publ......
  • 设计模式-原型模式
    原型模式(PrototypePattern):使用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。原型模式是一种对象创建型模式应用实例描述如下:未使用原型模式#inc......
  • 设计模式-建造者模式
    业务场景未使用建造者模式实现#include<iostream>#include<string>#include<vector>#include<sstream>usingnamespacestd;template<classT>stringConvertTo......
  • 原型链的问题
    1<!DOCTYPEhtml>2<htmllang="en">3<head>4<metacharset="UTF-8">5<title>原型链的问题</title>6</head>7<body>89<script>10......
  • 软件测试|测试开发之路--UI 自动化常用设计模式
    接上一次的帖子,今天讲一下我再UI自动化中常用的设计模式。由于网上已经有非常多的文章详细讲解了设计模式的编码实现,所以我今天也就不讲实现细节了。就是讲我也讲不出什......
  • php 运用设计模式:观察者模式,设计电商平台支付成功程序|Github仓库
    前(fei)言(hua)在支付程序中,大型项目的维护,如果没有运用到设计模式,面向过程的编程,order程序会日益增加,程序看上去杂乱无章,今天写了一个小demo,之前没有运用过观察者模式的小伙......
  • 关于工具软件:Apipost和Apifox哪个更好用看这篇就够了
    很多人搞不清楚Apipost和Apifox到底有什么区别,以下为实际体验,各位能够依据本身状况参考一下,有什么不足之处还请各位大佬多多指教。一、产品定位这块能够间接看他们的官网,个......