原型模式在23种设计模式中应用广泛,如何巧妙运用原型模式解决实际问题?

2026-03-30 14:561阅读0评论SEO问题
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1949个文字,预计阅读时间需要8分钟。

原型模式在23种设计模式中应用广泛,如何巧妙运用原型模式解决实际问题?

前言:在软件系统中,当创建一个类的实例的过程非常繁琐或复杂,并且我们需要创建多个这样的实例时,如果使用new操作符去创建这类实例,会增加创建类的复杂度和创建过程。

前言

在软件系统中,当创建一个类的实例的过程很昂贵或很复杂,并且我们需要创建多个这样类的实例时,如果我们用new操作符去创建这样的类实例,这就会增加创建类的复杂度和创建过程与客户代码复杂的耦合度。如果采用工厂模式来创建这样的实例对象的话,随着产品类的不断增加,导致子类的数量不断增多,也导致了相应工厂类的增加,维护的代码维度增加了,因为有产品和工厂两个维度了,反而增加了系统复杂程度,所以在这里使用工厂模式来封装类创建过程并不合适。由于每个类实例都是相同的,这个相同指的是类型相同,但是每个实例的状态参数会有不同,如果状态数值也相同就没意义了,有一个这样的对象就可以了。当我们需要多个相同的类实例时,可以通过对原来对象拷贝一份来完成创建,这个思路正是原型模式的实现方式。

原型模式的定义

在软件系统中,经常面临着“某些结构复杂的对象”的创建工作;由于需求的变化,这些对象经常面临着剧烈的变化,但是它们却拥有比较稳定一致的接口。如何应对这种变化?如何向“客户程序”隔离出“这些易变对象”,从而使得“依赖这些易变对象的客户程序”不随着需求改变而改变?那就是原型模式**,使用原型实例指定创建对象的种类,然后通过拷贝这些原型来创建新的对象。

原型模式的组成

  • 原型类(Prototype):原型类,声明一个Clone自身的接口;
  • 具体原型类(ConcretePrototype):实现一个Clone自身的操作。

在原型模式中,Prototype通常提供一个包含Clone方法的接口,具体的原型ConcretePrototype使用Clone方法完成对象的创建。

原型模式的实现

《大话西游之大圣娶亲》这部电影,没看过的人不多吧,里面有这样一个场景。牛魔王使用无敌牛虱大战至尊宝,至尊宝的应对之策就是,从脑后把下一撮猴毛,吹了口仙气,无数猴子猴孙现身,来大战牛魔王的无敌牛虱。至尊宝的猴子猴孙就是该原型模式的最好体现。至尊宝创建自己的一个副本,不用还要重新孕育五百年,然后出世,再学艺,最后来和老牛大战,估计黄花菜都凉了。他有3根救命猴毛,轻轻一吹,想要多少个自己就有多少个,方便,快捷。

抽象原型

/// <summary> /// 抽象原型,定义了原型本身所具有特征和动作,该类型就是至尊宝 /// </summary> public abstract class Prototype { /// <summary> /// 战斗--保护师傅 /// </summary> public abstract void Fight(); /// <summary> /// 化缘--不要饿着师傅 /// </summary> public abstract void BegAlms(); /// <summary> /// 吹口仙气--变化一个自己出来 /// </summary> /// <returns></returns> public abstract Prototype Clone(); }

具体原型

创建两个具体原型:行者孙和孙行者

行者孙:

原型模式在23种设计模式中应用广泛,如何巧妙运用原型模式解决实际问题?

/// <summary> /// 具体原型,例如:行者孙,他只负责化斋饭食和与天界宠物下界的妖怪的战斗 /// </summary> public sealed class XingZheSunPrototype : Prototype { /// <summary> /// 战斗--保护师傅--与自然修炼成妖的战斗 /// </summary> public override void Fight() { Console.WriteLine("行者孙:腾云驾雾,与天界宠物下界的妖怪的战斗...."); } /// <summary> /// 化缘--不要饿着师傅--饭食类 /// </summary> public override void BegAlms() { Console.WriteLine("行者孙:化缘鸡鱼肉蛋...."); } /// <summary> /// 吹口仙气--变化一个自己出来 /// </summary> /// <returns></returns> public override Prototype Clone() { return (XingZheSunPrototype)this.MemberwiseClone(); } }

孙行者:

/// <summary> /// 具体原型,例如:孙行者,他只负责与自然界修炼成妖的战斗和化斋水果 /// </summary> public sealed class SunXingZhePrototype : Prototype { /// <summary> /// 战斗--保护师傅-与天界宠物战斗 /// </summary> public override void Fight() { Console.WriteLine("孙行者:腾云驾雾,与自然界修炼成妖的战斗...."); } /// <summary> /// 化缘--不要饿着师傅---水果类 /// </summary> public override void BegAlms() { Console.WriteLine("孙行者:化缘水果...."); } /// <summary> /// 吹口仙气--变化一个自己出来 /// </summary> /// <returns></returns> public override Prototype Clone() { return (SunXingZhePrototype)this.MemberwiseClone(); } }

调用

public void RunTest() { //原型行者孙 Prototype xingZheSun = new XingZheSunPrototype(); Prototype xingZheSun2 = xingZheSun.Clone(); Prototype xingZheSun3 = xingZheSun.Clone(); //1号行者孙打妖怪 xingZheSun.Fight(); //2号行者孙去化缘 xingZheSun3.BegAlms(); Console.WriteLine("\r\n*****************************\r\n"); //原型孙行者 Prototype sunXingZhe = new SunXingZhePrototype(); Prototype sunXingZhe2 = sunXingZhe.Clone(); Prototype sunXingZhe3 = sunXingZhe.Clone(); Prototype sunXingZhe4 = sunXingZhe.Clone(); Prototype sunXingZhe5 = sunXingZhe.Clone(); //1号孙行者打妖怪 sunXingZhe.Fight(); //2号孙行者去化缘 sunXingZhe2.BegAlms(); //战斗和化缘也可以分类,比如化缘,可以分:水果类化缘,饭食类化缘;战斗可以分为:天界宠物下界成妖的战斗,自然修炼成妖的战斗,大家可以自己去想吧,原型模式还是很有用的 }

原型模式的优缺点

优点
  • 原型模式向客户隐藏了创建新实例的复杂性。
  • 原型模式允许动态增加或较少产品类。
  • 原型模式简化了实例的创建结构,工厂方法模式需要有一个与产品类等级结构相同的等级结构,而原型模式不需要这样。
  • 产品类不需要事先确定产品的等级结构,因为原型模式适用于任何的等级结构。
缺点
  • 每个类必须配备一个克隆方法。
  • 配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定很容易,特别当一个类引用不支持串行化的间接对象,或者引用含有循环结构的时候。

技术的发展日新月异,随着时间推移,无法保证本博客所有内容的正确性。如有误导,请大家见谅,欢迎评论区指正!

开源库地址,欢迎Star点亮:

GitHub:github.com/ITMingliang

Gitee:gitee.com/mingliang_it

GitLab:gitlab.com/ITMingliang


建群声明:本着技术在于分享,方便大家交流学习的初心,特此建立,为大家答疑解惑。热烈欢迎各位爱交流学习的程序员进群,也希望进群的大佬能不吝分享自己遇到的技术问题和学习心得!进群方式:扫码关注公众号,后台回复。

本文共计1949个文字,预计阅读时间需要8分钟。

原型模式在23种设计模式中应用广泛,如何巧妙运用原型模式解决实际问题?

前言:在软件系统中,当创建一个类的实例的过程非常繁琐或复杂,并且我们需要创建多个这样的实例时,如果使用new操作符去创建这类实例,会增加创建类的复杂度和创建过程。

前言

在软件系统中,当创建一个类的实例的过程很昂贵或很复杂,并且我们需要创建多个这样类的实例时,如果我们用new操作符去创建这样的类实例,这就会增加创建类的复杂度和创建过程与客户代码复杂的耦合度。如果采用工厂模式来创建这样的实例对象的话,随着产品类的不断增加,导致子类的数量不断增多,也导致了相应工厂类的增加,维护的代码维度增加了,因为有产品和工厂两个维度了,反而增加了系统复杂程度,所以在这里使用工厂模式来封装类创建过程并不合适。由于每个类实例都是相同的,这个相同指的是类型相同,但是每个实例的状态参数会有不同,如果状态数值也相同就没意义了,有一个这样的对象就可以了。当我们需要多个相同的类实例时,可以通过对原来对象拷贝一份来完成创建,这个思路正是原型模式的实现方式。

原型模式的定义

在软件系统中,经常面临着“某些结构复杂的对象”的创建工作;由于需求的变化,这些对象经常面临着剧烈的变化,但是它们却拥有比较稳定一致的接口。如何应对这种变化?如何向“客户程序”隔离出“这些易变对象”,从而使得“依赖这些易变对象的客户程序”不随着需求改变而改变?那就是原型模式**,使用原型实例指定创建对象的种类,然后通过拷贝这些原型来创建新的对象。

原型模式的组成

  • 原型类(Prototype):原型类,声明一个Clone自身的接口;
  • 具体原型类(ConcretePrototype):实现一个Clone自身的操作。

在原型模式中,Prototype通常提供一个包含Clone方法的接口,具体的原型ConcretePrototype使用Clone方法完成对象的创建。

原型模式的实现

《大话西游之大圣娶亲》这部电影,没看过的人不多吧,里面有这样一个场景。牛魔王使用无敌牛虱大战至尊宝,至尊宝的应对之策就是,从脑后把下一撮猴毛,吹了口仙气,无数猴子猴孙现身,来大战牛魔王的无敌牛虱。至尊宝的猴子猴孙就是该原型模式的最好体现。至尊宝创建自己的一个副本,不用还要重新孕育五百年,然后出世,再学艺,最后来和老牛大战,估计黄花菜都凉了。他有3根救命猴毛,轻轻一吹,想要多少个自己就有多少个,方便,快捷。

抽象原型

/// <summary> /// 抽象原型,定义了原型本身所具有特征和动作,该类型就是至尊宝 /// </summary> public abstract class Prototype { /// <summary> /// 战斗--保护师傅 /// </summary> public abstract void Fight(); /// <summary> /// 化缘--不要饿着师傅 /// </summary> public abstract void BegAlms(); /// <summary> /// 吹口仙气--变化一个自己出来 /// </summary> /// <returns></returns> public abstract Prototype Clone(); }

具体原型

创建两个具体原型:行者孙和孙行者

行者孙:

原型模式在23种设计模式中应用广泛,如何巧妙运用原型模式解决实际问题?

/// <summary> /// 具体原型,例如:行者孙,他只负责化斋饭食和与天界宠物下界的妖怪的战斗 /// </summary> public sealed class XingZheSunPrototype : Prototype { /// <summary> /// 战斗--保护师傅--与自然修炼成妖的战斗 /// </summary> public override void Fight() { Console.WriteLine("行者孙:腾云驾雾,与天界宠物下界的妖怪的战斗...."); } /// <summary> /// 化缘--不要饿着师傅--饭食类 /// </summary> public override void BegAlms() { Console.WriteLine("行者孙:化缘鸡鱼肉蛋...."); } /// <summary> /// 吹口仙气--变化一个自己出来 /// </summary> /// <returns></returns> public override Prototype Clone() { return (XingZheSunPrototype)this.MemberwiseClone(); } }

孙行者:

/// <summary> /// 具体原型,例如:孙行者,他只负责与自然界修炼成妖的战斗和化斋水果 /// </summary> public sealed class SunXingZhePrototype : Prototype { /// <summary> /// 战斗--保护师傅-与天界宠物战斗 /// </summary> public override void Fight() { Console.WriteLine("孙行者:腾云驾雾,与自然界修炼成妖的战斗...."); } /// <summary> /// 化缘--不要饿着师傅---水果类 /// </summary> public override void BegAlms() { Console.WriteLine("孙行者:化缘水果...."); } /// <summary> /// 吹口仙气--变化一个自己出来 /// </summary> /// <returns></returns> public override Prototype Clone() { return (SunXingZhePrototype)this.MemberwiseClone(); } }

调用

public void RunTest() { //原型行者孙 Prototype xingZheSun = new XingZheSunPrototype(); Prototype xingZheSun2 = xingZheSun.Clone(); Prototype xingZheSun3 = xingZheSun.Clone(); //1号行者孙打妖怪 xingZheSun.Fight(); //2号行者孙去化缘 xingZheSun3.BegAlms(); Console.WriteLine("\r\n*****************************\r\n"); //原型孙行者 Prototype sunXingZhe = new SunXingZhePrototype(); Prototype sunXingZhe2 = sunXingZhe.Clone(); Prototype sunXingZhe3 = sunXingZhe.Clone(); Prototype sunXingZhe4 = sunXingZhe.Clone(); Prototype sunXingZhe5 = sunXingZhe.Clone(); //1号孙行者打妖怪 sunXingZhe.Fight(); //2号孙行者去化缘 sunXingZhe2.BegAlms(); //战斗和化缘也可以分类,比如化缘,可以分:水果类化缘,饭食类化缘;战斗可以分为:天界宠物下界成妖的战斗,自然修炼成妖的战斗,大家可以自己去想吧,原型模式还是很有用的 }

原型模式的优缺点

优点
  • 原型模式向客户隐藏了创建新实例的复杂性。
  • 原型模式允许动态增加或较少产品类。
  • 原型模式简化了实例的创建结构,工厂方法模式需要有一个与产品类等级结构相同的等级结构,而原型模式不需要这样。
  • 产品类不需要事先确定产品的等级结构,因为原型模式适用于任何的等级结构。
缺点
  • 每个类必须配备一个克隆方法。
  • 配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定很容易,特别当一个类引用不支持串行化的间接对象,或者引用含有循环结构的时候。

技术的发展日新月异,随着时间推移,无法保证本博客所有内容的正确性。如有误导,请大家见谅,欢迎评论区指正!

开源库地址,欢迎Star点亮:

GitHub:github.com/ITMingliang

Gitee:gitee.com/mingliang_it

GitLab:gitlab.com/ITMingliang


建群声明:本着技术在于分享,方便大家交流学习的初心,特此建立,为大家答疑解惑。热烈欢迎各位爱交流学习的程序员进群,也希望进群的大佬能不吝分享自己遇到的技术问题和学习心得!进群方式:扫码关注公众号,后台回复。