设计模式之原型模式(Prototype)(五)

。_饼干妹妹 提交于 2020-03-27 18:16:34

3 月,跳不动了?>>>

动机

在软件系统中,经常面临着“某些结构复杂的对象”的创建工作;由于需求的变化,这些对象经常面临着剧烈的变化,但是它们却拥有比较稳定一致的接口。

如何应对这种变化?如何向“客户程序(使用这些对象的程序)”隔离出“这些易变对象” ,从而使得“依赖这些易变对象的客户程序”不随着需求改变而改变?

 

意图

使用原型实例指定创建对象的种类,然后通过拷贝这些原型来创建新的对象

 

示意图

原型设计模式代码实现

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

namespace 原型模式
{
    class Program
    {
        static void Main(string[] args)
        {
            Computer computer = new Computer();
            computer.name = "Dell.X5124";
            computer.age = 5;
            computer.factory = new Factory() { name = "Dell" };
            computer.factory.manage = new Manage(){ManageName = "Nick"};

            Computer C1 = (computer as ICloneable).Clone() as Computer;
            C1.name = "Dell.X2546";
            C1.age = 6;
            C1.factory.name = "Sam";
            C1.factory.manage.ManageName = "jack";
            Console.WriteLine(computer);
            Console.WriteLine(C1);
            Console.ReadLine();
            
        }
    }

    public class Computer:ICloneable
    {
        public string name { get; set; }
        public int age { get; set; }

        public Factory factory { get; set; }

       


        public object Clone()
        {
            //return this.MemberwiseClone();//浅复制

            //以下实现深Copy

            var _Instace = this.MemberwiseClone() as Computer;
            _Instace.factory = (this.factory as ICloneable).Clone() as Factory;
            return _Instace;


        }

        public override string ToString()
        {
            return string.Format("电脑名字{0},使用年限{1},工厂名字{2},工厂管理者{3}",this.name,this.age,this.factory.name,this.factory.manage.ManageName);
        }
    }

    public class Factory:ICloneable
    {
        public string name { get; set; }
        public Manage manage { get; set; }

        public object Clone()//深Copy
        {
            var _Instace = base.MemberwiseClone() as Factory;
            _Instace.manage = (this.manage as ICloneable).Clone() as Manage;
            return _Instace;
        }
    }

    public class Manage:ICloneable
    {
        public string ManageName { get; set; }


        public object Clone()//浅Copy
        {
            return base.MemberwiseClone();
        }
    }

}
 

ICloneable和DataSet

 

ICloneable

public object Clone();

 

实现ICloneable接口,即可实现Prototype模式

 

DataSet

 

4lone():只复制结构,不复制数据à浅复制

Copy();复制结构,也复制数据à深复制

 

浅Copy与深Copy

如果一个对象是复合对象或者包含其他的对象,那么克隆对象的问题是仅仅复制对象本身,还是连同被引用的对象一起复制?

实现IClone接口的类基本上都采用浅复制的策略

MemberwiseClone():

值类型:逐位复制

引用类型:只复制引用(指针)但不复制引用的对象

深复制:把引用对象的变量,指向复制过的,新的对象,而不是原有的被引用的对象

 

实现要点

善用ICloneable接口

产品的创建和初始化在类的Clone方法中完成

浅复制与深复制的区别

需要深复制的场合需要开发人员根据需要实现

有些情况下Clone功能不容易实现,特别是遇到对象的循环引用时

 

功能

在运行时增加或删除产品:只要通过客户原型实例即可将新产品类型增加到系统中,例如组态软件中工具箱中的每个工具可以对应一个注册的原型对象,可以通过增加原形对象扩展工具箱。

很容易地创建复杂的对象:在图形编辑和组态等软件中,经常需要创建复杂的图元。这些图元是由简单图元组成的,采用原型模式可以很容易地将复杂图元作为一般图元来使用,使软件的工具箱具有自扩展功能

 

适用性

当一个系统应该独立于产品的创建、构成和表示时,可以使用原型模式。

在使用时,我们可以用一些原型对象来代替生成相应对象的工厂对象,并且可以使拷贝、粘贴等操作独立于需要复制的对象。

 

总结

Prototype模式同样用于隔离类对象的使用者和具体类型(易变类)之间的耦合关系,它同样要求这些“易变类”拥有“稳定的接口”。

Prototype模式对于“如何创建易变类的实体对象”采用“原型克隆”的方法来做,它使得我们可以非常灵活地动态创建“拥有某些稳定接口”的新对象——所需工作仅仅是注册一个新的对象(即原型),然后在任何需要的地方不断地Clone。

Prototype模式中的Clone方法可以利用.NET中的Object类的MemberwiseClone()方法或者序列化来实现深拷贝。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!