大话设计模式:抽象工厂模式

一、什么是抽象工厂模式
提供一个接口创建一组或一系列相关或互相依赖的对象

抽象工厂主要是针对种类繁多,需要一系列的对象组合的情况,而每次只需要实例其中的一组系列。是工厂模式的升级,进一步抽象,工厂模式只能生产一个等级的产品,而抽象工厂能生产多个等级的一个系列的产品。

UML图

在这里插入图片描述
AbstractFactory: 抽象工厂,定义一系列有关联的接口
ConcreteFactory:实现具体的接口对象,实现不同级别的产品组合.
AbstractProduct: 抽象产品,定义一个级别的产品,多个抽象产品分别定义不同级别的产品

二、适用场景

每一系列产品具有不同级别的产品,比如格力系列家电,空调/洗衣机/冰箱, 海尔系列家电,空调/洗衣机/冰箱。 空调和空调就是同一级别的产品, 空调、洗衣机、冰箱就是不同级别的产品,但是又可以属于同一品牌,具有关联性。
当需要创建的对象是一些列相互关联或相互依赖的产品族时,便可以使用抽象工厂模式。也就是说一个继承体系中,如果存在着多个等级结构(相当于多个抽象类),并且分属各个等级结构中的实现类之间存在着一定的关联或约束,就可以使用抽象工厂模式。假如各个等级结构中的实现类之间不存在关联或约束,则使用多个独立的工厂来对产品进行创建,则更适合一点。

三、优缺点

优点
在内部对产品族进行约束,同一个产品族之间的产品应具备某些关联
在类的内部对产品族中相关联的多等级产品共同管理,而不必专门引入多个新的类来进行管理。
当增加一个新的产品族时,不需要修改代码。
缺点
当需要增加一个新的产品时,所有的工厂类都需要修改

四、大话中的例子

各种数据库的实现是sql还是 accesst ,每一类数据库里面又包含不同级别的内容,比如用户名、依赖文件。有一个抽象工厂类里面定义 用户名、依赖文件的方法, 具体的sql工厂方法则实现 sql的用户名, sql的依赖文件, 具体的accesst工厂方法则实现accesst的用户名,accesst的依赖方法。

五、我的例子

抽象工厂模式

using System;


namespace AbstractFactory
{
    class Program
    {
        static void Main(string[] args)
        {

             NinjaTeam ninjaTeam = new KonohaVillage();
            //NinjaTeam ninjaTeam = new SandVillage();
            ninjaTeam.AddDpsNinja().TaskDamage(99);
            ninjaTeam.AddMedicalNinja().Iatrotechnics(50);
            ninjaTeam.AddTrackNinja().TrackPos();
            Console.ReadKey();

        }
    }

    /// <summary>
    /// 忍者
    /// </summary>
    public abstract class Ninja
    {
        string name;
        public string Name { get { return name; } }
        public Ninja(string name)
        {
            this.name = name;
        }
    }

    /// <summary>
    /// 医疗忍者
    /// </summary>
    public abstract class MedicalNinja : Ninja
    {
        public MedicalNinja(string name) : base(name)
        {
        }

        /// <summary>
        /// 治疗术
        /// </summary>
        /// <param name="ninja"></param>
        public void Iatrotechnics(int hp)
        {
            Console.WriteLine("{0}为队友恢复生命值{1}点", Name, hp);
        }
    }

    /// <summary>
    /// 追踪忍者
    /// </summary>
    public abstract class TrackNinja : Ninja
    {
        public TrackNinja(string name) : base(name)
        {
        }

        /// <summary>
        /// 追踪术
        /// </summary>
        public void TrackPos()
        {
            Console.WriteLine("{0}在追纵敌人的踪迹", Name);
        }
    }


    /// <summary>
    /// 输出忍者
    /// </summary>
    public abstract class DpsNinja : Ninja
    {
        public DpsNinja(string name) : base(name)
        {
        }

        /// <summary>
        /// 输出
        /// </summary>
        /// <param name="damage"></param>
        public void TaskDamage(int damage)
        {
            Console.WriteLine("{1}对敌人造成{0}点伤害", damage, Name);
        }
    }


    /// <summary>
    /// 小樱
    /// </summary>
    public class Sakura : MedicalNinja
    {
        public Sakura(string name) : base(name)
        {
        }
    }

    /// <summary>
    /// 佐井
    /// </summary>
    public class Sai : TrackNinja
    {
        public Sai(string name) : base(name)
        {
        }
    }

    /// <summary>
    /// 鸣人
    /// </summary>
    public class Naruto : DpsNinja
    {
        public Naruto(string name) : base(name)
        {
        }
    }

    /// <summary>
    /// 手鞠
    /// </summary>
    public class Temari : MedicalNinja
    {
        public Temari(string name) : base(name)
        {
        }
    }

    /// <summary>
    /// 勘九郎
    /// </summary>
    public class Kankuro : TrackNinja
    {
        public Kankuro(string name) : base(name)
        {
        }
    }

    /// <summary>
    /// 我爱罗
    /// </summary>
    public class Gaara : DpsNinja
    {
        public Gaara(string name) : base(name)
        {
        }
    }


    /// <summary>
    /// 忍者小队三人组
    /// </summary>
    public abstract class NinjaTeam
    {
        public abstract MedicalNinja AddMedicalNinja();
        public abstract TrackNinja AddTrackNinja();
        public abstract DpsNinja AddDpsNinja();
    }


    /// <summary>
    /// 木叶村小队
    /// </summary>
    public class KonohaVillage : NinjaTeam
    {
        public override DpsNinja AddDpsNinja()
        {
            return new Naruto("鸣人");
        }

        public override MedicalNinja AddMedicalNinja()
        {
            return new Sakura("小樱");
        }

        public override TrackNinja AddTrackNinja()
        {
            return new Sai("佐井");
        }
    }

    /// <summary>
    /// 砂隐村小队
    /// </summary>
    public class SandVillage : NinjaTeam
    {
        public override DpsNinja AddDpsNinja()
        {
            return new Gaara("我爱罗");
        }

        public override MedicalNinja AddMedicalNinja()
        {
            return new Temari("手鞠");
        }

        public override TrackNinja AddTrackNinja()
        {
            return new Kankuro("勘九郎");
        }
    }

}

运行结果

在这里插入图片描述

把木叶小队换成砂隐小队,只需要把NinjaTeam ninjaTeam = new KonohaVillage(); 更改为NinjaTeam ninjaTeam = new SandVillage();其它都不用变。

运行结果

在这里插入图片描述

抽象工厂结合简单工厂
只需要将上述的NinjaTeam SandVillage KonohaVillage 这三个类用一个简单工厂类代替,不同系列用 switch区分.

 public class DataAccess
    {
        // string VillageName = "konoha";
        string VillageName = "sand";

        public MedicalNinja AddMedicalNinja()
        {
            MedicalNinja medicalNinja = null; ;
            switch (VillageName)
            {

                case "konoha":
                    medicalNinja = new Sakura("小樱");
                    break;
                case "sand":
                    medicalNinja = new Temari("手鞠");
                    break;
            }
            return medicalNinja;
        }


        public TrackNinja AddTrackNinja()
        {
            TrackNinja trackNinja = null;
            switch (VillageName)
            {
                case "konoha":
                    trackNinja = new Sai("佐井");
                    break;
                case "sand":
                    trackNinja = new Kankuro("勘九郎");
                    break;
            }
            return trackNinja;
        }
        public DpsNinja AddDpsNinja()
        {
            DpsNinja dpsNinja = null;
            switch (VillageName)
            {
                case "konoha":
                    dpsNinja = new Naruto("鸣人");
                    break;
                case "sand":
                    dpsNinja = new Gaara("我爱罗");
                    break;
            }
            return dpsNinja;
        }
    }

抽象工厂结合简单工厂结合反射

using System;
using System.Reflection;

namespace AbstractFactory
{
    class Program
    {
        static void Main(string[] args)
        {

     
            ReflectDataAccess reflectDataAccess = new ReflectDataAccess();
            DpsNinja dpsNinja = reflectDataAccess.AddDpsNinja();

            dpsNinja.TaskDamage(78);
            reflectDataAccess.AddMedicalNinja().Iatrotechnics(30);
            Console.ReadKey();

        }
    }
    public class SandMedical : MedicalNinja
    {
        public SandMedical(string name) : base(name)
        {


        }
        public SandMedical() { Name = "千代婆婆"; }
    }

    public class SandDps : DpsNinja
    {
        public SandDps()
        {
            Name = "赤砂之蝎";
        }
        public SandDps(string name) : base(name)
        {
        }
    }

    public class KonohaMedical : MedicalNinja
    {
        public KonohaMedical()
        {
            Name = "纲手";
        }

        public KonohaMedical(string name) : base(name)
        {


        }
    }
    public class KonohaDps : DpsNinja
    {
        public KonohaDps()
        {
            Name = "自来也";
        }
        public KonohaDps(string name) : base(name)
        {
        }

    }

    public enum EVillageName
    {
        Sand,
        Konoha,
    }

    /// <summary>
    /// 利用反射性质的简单工厂
    /// </summary>
    public class ReflectDataAccess
    {

        private static readonly string AssemblyName = "AbstractFactory";//程序集名
        private static readonly string VillageName = EVillageName.Konoha.ToString(); //限制名


        public MedicalNinja AddMedicalNinja()
        {
            string className = AssemblyName + "." + VillageName + "Medical";//类的完整名
            object[] obj = new object[1];
            obj[0] = "大哥";
           return (MedicalNinja)Assembly.Load(AssemblyName).CreateInstance(className);//用类名字符串返回一个类对象
            //return (MedicalNinja)Assembly.Load(AssemblyName).CreateInstance(className, true, BindingFlags.Default, null, obj, null, null);//带参构造函数的使用
        }

        public DpsNinja AddDpsNinja()
        {
            string className = AssemblyName + "." + VillageName + "Dps";
            return (DpsNinja)Assembly.Load(AssemblyName).CreateInstance(className);

        }
    }
  }
 运行结果

在这里插入图片描述

将 private static readonly string VillageName = EVillageName.Konoha.ToString(); //限制名
改为 private static readonly string VillageName = EVillageName.Sand.ToString(); //限制名

  运行结果

在这里插入图片描述

PS:抽象工厂模式的使用非常具有针对性,适用于产品族丰富,产品等级确定无变化的情况,增加族群只需要增加相应的具体族群工厂,每一个抽象等级产品下派生该族群的产品即可,只需要添加类,不需要修改,但如果要添加某一产品,那需要改动的就太多了, 抽象工厂类/具体工厂类/都要修改,还要增加抽象等级产品。 结合简单工厂模式能部分避免一些问题,但依旧显得繁琐。再结合反射的原理,可以大大节约简单工厂中的 条件分支语句。如果是针对抽象工厂的衍生,在具体产品类起名字的时候就得非常注意规整性,否则使用反射就很难控制, 而只是单纯的简单工厂就没有这个顾虑了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值