zoukankan      html  css  js  c++  java
  • 设计模式(5)原型模式(Prototype)

    设计模式(0)简单工厂模式

    设计模式(1)单例模式(Singleton)

    设计模式(2)工厂方法模式(Factory Method)

    设计模式(3)抽象工厂模式(Abstract Factory)

    设计模式(4)建造者模式/生成器模式(Builder)

    源码地址

    0 原型模式简介

    0.0 原型模式定义

    原型模式是一种常用的创建型模式,原型模式的一般定义为用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象

    原型模式要求对象必须具有一个可以“克隆”自身的方法,这样就可以通过这个克隆自身的方法创建一个新的同一类型的实例。我们通常将这个克隆自身的方法定义在抽象的接口上,直接通过接口调用其内部包含的克隆方法,创建一个具体的对象。这样就可以实现通过原型模式创建具体对象,无需关注这个对象本身的类型,也不用关心其内部的具体实现,而无须再去通过new去创建具体的类型的实例。

    原型模式的结构图如下

    timg

    Prototype:声明一个克隆自身的接口,用来约束想要克隆自身的类,所有想要实现克隆自身这一功能的类需要继承此接口,并且实现该接口里定义的克隆自身的方法

    ConcretePrototype:实现了Prototype接口的具体实现类,这些类中负责Clone这一方法的具体实现

    Client:客户端,通过原型实例克隆自身的Clone方法创建新的对象实例

    0.1 原型模式应用场景

    在war3中,有一个道具叫做“幻象权杖”其作用是使用后能制造目标单位的一个幻象。我们不考究幻象的其他具体细节,从外形上是与本体完全一摸一样的。

    我们先创建一个英雄的接口

    /// <summary>
    /// 英雄接口定义
    /// </summary>
    public interface IHero
    {
        /// <summary>
        /// 身体特征
        /// </summary>
        string Body { get; set; }
    
        /// <summary>
        /// 武器
        /// </summary>
        string Weapon { get; set; }
    
        /// <summary>
        /// 坐骑
        /// </summary>
        string Mount { get; set; }
    }

    DH类具体实现

    /// <summary>
    /// 恶魔猎手
    /// </summary>
    public class DH : IHero
    {
    
        /// <summary>
        /// 身体特征
        /// </summary>
        public string Body
        {
            get { return "黑夜给了我黑色眼睛,我却用它去寻找光明。"; }
            set { }
        }
    
        /// <summary>
        /// 武器
        /// </summary>
        public string Weapon
        {
            get { return "艾辛诺斯双刃。"; }
            set { }
        }
    
        /// <summary>
        /// 坐骑
        /// </summary>
        public string Mount
        {
            get { return "我有这双脚有这双腿。"; }
            set { }
        }
    }

    POM类具体实现

    /// <summary>
    /// 月亮女祭司
    /// </summary>
    public class POM : IHero
    {
        /// <summary>
        /// 身体特征
        /// </summary>
        public string Body
        {
            get { return "夜幕只为朱颜改,群星陨落无穷。"; }
            set { }
        }
    
        /// <summary>
        /// 武器
        /// </summary>
        public string Weapon
        {
            get { return "索利达尔·群星之怒。"; }
            set { }
        }
    
        /// <summary>
        /// 坐骑
        /// </summary>
        public string Mount
        {
            get { return "艾斯卡达尔。"; }
            set { }
        }
    }

    幻象权杖类实现

    /// <summary>
    /// 幻象权杖
    /// </summary>
    public class WandOfIllusion
    {
        public static IHero Use(IHero hero)
        {
            IHero result = null;
            if (hero is DH)
            {
                result = new DH();
            }
            else if (hero is POM)
            {
                result = new POM();
            }
            return result;
        }
    }

    客户端使用

    class Program
    {
        static void Main(string[] args)
        {
            DH dh = new DH();
            var dh1 = WandOfIllusion.Use(dh); // 对dh使用幻象权杖
            Console.ReadLine();
        }
    }

    这样可以实现英雄使用幻象权杖复制自身这一基本需求,但是明显存在一下问题

    1、通过幻象权杖复制英雄对象本身 这一通用的功能代码中,不应该强依赖具体的英雄类,应该是与具体的实现无关的。

    2、难以扩展,要实现其他英雄使用幻象权杖这一操作,就必须修改幻象权杖类,里面需要增加更多的类型判断。而且我们这里只做了简要的对象创建处理,而实际中各个对象的创建过程是千差万别的,这样我们的幻象权杖类就会变得越来越难以维护。

    基于问题的出现以及上述对原型模式的介绍,我们可以使用原型模式解决这一问题。

    1 原型模式详解

    0、英雄接口增加Clone方法

    按照原型模式的要求,我们需要在英雄接口中增加一个Clone方法,所有英雄的具体实现类实现此方法,完成复制英雄的具体细节。

    /// <summary>
    /// 英雄接口定义
    /// </summary>
    public interface IHero
    {
        /// <summary>
        /// 身体特征
        /// </summary>
        string Body { get; set; }
    
        /// <summary>
        /// 武器
        /// </summary>
        string Weapon { get; set; }
    
        /// <summary>
        /// 坐骑
        /// </summary>
        string Mount { get; set; }
    
        /// <summary>
        /// Clone本身接口定义
        /// </summary>
        /// <returns></returns>
        IHero Clone();
    }

    1、具体英雄实现类实现Clone方法

    /// <summary>
    /// 恶魔猎手
    /// </summary>
    public class DH : IHero
    {
    
        /// <summary>
        /// 身体特征
        /// </summary>
        public string Body
        {
            get { return "黑夜给了我黑色眼睛,我却用它去寻找光明。"; }
            set { }
        }
    
        /// <summary>
        /// 武器
        /// </summary>
        public string Weapon
        {
            get { return "艾辛诺斯双刃。"; }
            set { }
        }
    
        /// <summary>
        /// 坐骑
        /// </summary>
        public string Mount
        {
            get { return "我有这双脚有这双腿。"; }
            set { }
        }
    
        /// <summary>
        /// Clone
        /// </summary>
        /// <returns></returns>
        public IHero Clone()
        {
            IHero hero = new DH();
            //TODO:进行其他Clone相关操作
            return hero;
        }
    }
    /// <summary>
    /// 月亮女祭司
    /// </summary>
    public class POM : IHero
    {
        /// <summary>
        /// 身体特征
        /// </summary>
        public string Body
        {
            get { return "夜幕只为朱颜改,群星陨落无穷。"; }
            set { }
        }
    
        /// <summary>
        /// 武器
        /// </summary>
        public string Weapon
        {
            get { return "索利达尔·群星之怒。"; }
            set { }
        }
    
        /// <summary>
        /// 坐骑
        /// </summary>
        public string Mount
        {
            get { return "艾斯卡达尔。"; }
            set { }
        }
    
        /// <summary>
        /// Clone
        /// </summary>
        /// <returns></returns>
        public IHero Clone()
        {
            IHero hero = new POM();
            //TODO:进行其他Clone相关操作
            return hero;
        }
    }

    2、修改幻象权杖类

    /// <summary>
    /// 幻象权杖
    /// </summary>
    public class WandOfIllusion
    {
        public static IHero Use(IHero hero)
        {
            IHero result = null;
            //if (hero is DH)
            //{
            //    result = new DH();
            //}
            //else if (hero is POM)
            //{
            //    result = new POM();
            //}
            result = hero.Clone();
            return result;
        }
    }

    至此我们的幻象权杖通用类,已经与具体的英雄实现类无关了。

    3、浅克隆和深克隆

    浅克隆:只克隆值类型的属性数据

    深克隆:除了要复制浅克隆需要复制的值类型属性数据外,也要复制引用类型的属性数据。

    2 总结

    优点

    对客户端调用隐藏具体实现类细节,减少外部调用对具体实现类的依赖

    缺点

    每个实现类都必须实现Clone方法,尤其在包含引用类型的深克隆时,需要逐级让所有的引用类型实现Clone

  • 相关阅读:
    最小二乘拟合(scipy实现)
    接口实例
    类的继承:员工和老板
    设计模式(Design Patterns)
    创建类
    面向对象1
    java随机数:彩票抽奖 + 验证码
    判断字符串中字符出现的次数+去除空格
    输出二维数组所有元素的和
    输出 一维数组中最大的数+数组遍历
  • 原文地址:https://www.cnblogs.com/fonour/p/7724511.html
Copyright © 2011-2022 走看看