设计模式学习之旅——简单工厂、工厂方法、抽象工厂

其实看设计模式已有一段时间了,主要是看《大话设计模式》还有四人帮的《设计模式》,总觉得理解的不够全面,这应该跟项目经验有关系,所谓的理论和实践并重。但又觉得学习本来就是这样,对一个知识有一定了解,以后运用或磕碰时再刷新对这个知识的认知,学学还是有好处的~

用个故事来描述吧,以下故事为虚实结合而成......

小白正在为公司开发一款射击类游戏,负责的是选枪的模块;提交的代码如下

     static void Main(string[] args)  //客户端代码
        {
            Console.WriteLine("请输入要选择的武器:A.步枪 B.机关枪 C.狙击枪");
            string fireType = Console.ReadLine();
            Weapon fireWeapon = null;
            switch (fireType)
            {
                case "A":
                    fireWeapon = new 步枪();
                    break;
                case "B":
                    fireWeapon = new 机关枪();
                    break;
                case "C":
                    fireWeapon = new 狙击枪();
                    break;
                default:
                    Console.WriteLine("请选择正确的武器");
                    break;
            }
        }

        abstract class Weapon
        {
            //...武器抽象类
        }

        class 步枪:Weapon
        {
            //...省略
        }
        class 机关枪:Weapon
        {
            //...省略
        }
        class 狙击枪:Weapon
        {
            //...省略
        }

提交代码后小白正哼着愉悦的曲子准备打卡,突然那熟悉而又鬼魅的声音打断他。

总监突然出现在后面说道:"小白,去吃饭啦?赶紧去~吃饭回来啊~”。

小白:"其实我是下...班"。

总监:"你看你写些什么!还下班,你怎么可以这么写呢?什么都塞到客户端,这样客户端代码多恶心啊!别吃饭了,快使用简单工厂模式改改!"

"...好,我这就改!",小白说道。

不一会儿,小白的代码改出来了:

        static void Main(string[] args)
        {
            Console.WriteLine("请输入要选择的武器:A.步枪 B.机关枪 C.狙击枪");
            string fireType = Console.ReadLine();
            Weapon fireWeapon = WeaponFactory.createWeapon(fireType);
        }

        abstract class Weapon
        {
            //...武器抽象类
        }

        class 步枪:Weapon
        {
            //...省略
        }
        class 机关枪:Weapon
        {
            //...省略
        }
        class 狙击枪:Weapon
        {
            //...省略
        }

        //增加一个工厂类
        public class WeaponFactory
        {
            public static Weapon createWeapon(string fireType)
            {
                Weapon fireWeapon = null;
                switch (fireType)
                {
                    case "A":
                        fireWeapon = new 步枪();
                        break;
                    case "B":
                        fireWeapon = new 机关枪();
                        break;
                    case "C":
                        fireWeapon = new 狙击枪();
                        break;
                    default:
                        Console.WriteLine("请选择正确的武器");
                        break;
                }
                return fireWeapon;
            }
        }

总监:"恩,这样客户端整洁了,而且还能把这个功能复用到web等程序中。"

简单工厂:就是运用基本的继承多态和抽取工厂方法到达代码整洁和方法复用,自己总结的,书上并没有定义。

总监:"但是我现在要添加一个武器怎么办?"

小白:"增加一个"Weapon的子类和增加一个case条件咯"

总监:"那是不是违反了面向对象的开闭原则(不能修改已经写好的类,只能扩展),我一天增加一种新武器,你这个类岂不是要改烂?赶紧用工厂方法改一下"

小白:"我肚子饿了..."

不一会儿,小白的代码又改出来了:

        static void Main(string[] args)  //客户端代码
        {
            Console.WriteLine("请输入要选择的武器:A.步枪 B.机关枪 C.狙击枪");
            string fireType = Console.ReadLine();
            Weapon fireWeapon = null;
            switch (fireType)
            {
                case "A":
                    fireWeapon = new 步枪工厂().CreateWeapon();
                    break;
                case "B":
                    fireWeapon = new 机关枪工厂().CreateWeapon();
                    break;
                case "C":
                    fireWeapon = new 狙击枪工厂().CreateWeapon();
                    break;
                default:
                    Console.WriteLine("请选择正确的武器");
                    break;
            }
        }

        abstract class Weapon
        {
            //...武器抽象类
        }

        class 步枪:Weapon
        {
            //...省略
        }
        class 机关枪:Weapon
        {
            //...省略
        }
        class 狙击枪:Weapon
        {
            //...省略
        }

        interface  IFactory
        {
            //...工厂接口
            Weapon CreateWeapon();
        }

        class 步枪工厂 : IFactory
        {
            public Weapon CreateWeapon()
            {
                return new 步枪();
            }
        }

        class 机关枪工厂 : IFactory
        {
            public Weapon CreateWeapon()
            {
                return new 机关枪();
            }
        }

        class 狙击枪工厂 : IFactory
        {
            public Weapon CreateWeapon()
            {
                return new 狙击枪();
            }
        }

小白:"这样子就解决了工厂方法的问题啦,这样只要在有新增的武器我就加个武器类和相应的工厂类就行啦~吃饭咯~"

有个问题困扰了我很久,什么工厂方法,不觉得代码看起来跟一开始一样吗?只是套了个工厂的壳,还不如直接创建对象,我觉得有这样的想法还是因为项目经验的不足导致的。直到我看到了百度百科中提到java的collection中的iterator运用了工厂方法(这里可以把list看做工厂,list.iterator就是创建对象的工厂方法)。设计模式多数可能是嵌套应用在某一个特定场景,所以当你遇到这些场景之后才能算真正理解设计模式带来的好处。

”工厂方法模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中“这个是设计模式书中的原话,一直都不知道他什么意思,也是看到下面java迭代器的例子才明白(创建出来的是什么迭代器,完全是由集合的子类来决定的,附java代码)

List list=new ArrayList();
Iterator iter = list.iterator();
while(iter.hasNext())
{
    //do something...
}

总监:"嗯...问题是解决了,可是客户端又变恶心了,赶紧去给我处理下,用反射什么的试试...这么晚了外面餐馆也关门了,待会请你吃泡面吧"

小白:"卧槽都饿扁了吃泡面哪够...."

        private static readonly string AssemblyName = "当前程序集名称";
        private static readonly string factory = ConfigurationManager.AppSettings["factory"];
        static void Main(string[] args)  //客户端代码
        {
            IFactory weaponFactory = (IFactory)Assembly.Load("当前程序集名称").CreateInstance("当前程序集名称" + "." + factory);            Weapon.fireWeapon= weaponFactory.CreateWeapon();
        }

//....下面的代码与上面一样,省略

小白:"这样只要在配置文件中更改要创建的武器名字就可以啦~"

总监:"恩...好吧,今天就到这里,给你泡面,下班吧。"

小白:"ye!!泡面泡起来!"

客户:"等下,小白同学,我这里怎么报错了奇怪了,你过来看看"

小白:"卧槽客户你哪冒出来的,这么晚了还在这里!"

小白:"......卧槽你搞什么,步枪的子弹怎么能跟火箭筒一起用!?"

客户:"不小心按到.....不对,都怪你,怎么可以让我按错呢,你程序不应该有什么容错性的吗?赶紧给我改!"

总监:"还不快去改!用抽象工厂试试!"

小白:"我..要..睡觉TT"

        private static readonly string AssemblyName = "当前程序集名称";
        private static readonly string factory = ConfigurationManager.AppSettings["factory"];
        static void Main(string[] args)  //客户端代码
        {
            IFactory weaponFactory = (IFactory)Assembly.Load("当前程序集名称").CreateInstance("当前程序集名称" + "." + factory);
            Weapon fireWeapon = weaponFactory.CreateWeapon();
            Bullet fireBullet =weaponFactory.CreateBullet();
        }

        abstract class Weapon
        {
            //...武器抽象类
        }

        class 步枪:Weapon
        {
            //...省略
        }
        class 机关枪:Weapon
        {
            //...省略
        }
        class 狙击枪:Weapon
        {
            //...省略
        }
        abstract class Bullet
        {
            //...子弹抽象类
        }
        class 步枪子弹 : Bullet
        {
            //...省略
        }
        class 机关枪子弹 : Bullet
        {
            //...省略
        }
        class 狙击枪子弹 : Bullet
        {
            //...省略
        }

        interface  IFactory
        {
            //...工厂接口
            Weapon CreateWeapon();
            Bullet CreateBullet();
        }

        class 步枪工厂 : IFactory
        {
            public Weapon CreateWeapon()
            {
                return new 步枪();
            }
            public Bullet CreateBullet()
            {
                return new 步枪子弹();
            }
        }

        class 机关枪工厂 : IFactory
        {
            public Weapon CreateWeapon()
            {
                return new 机关枪();
            }
            public Bullet CreateBullet()
            {
                return new 机关枪子弹();
            }
        }

        class 狙击枪工厂 : IFactory
        {
            public Weapon CreateWeapon()
            {
                return new 狙击枪();
            }
            public Bullet CreateBullet()
            {
                return new 狙击枪子弹();
            }
        }

天亮了,小白还在敲代码

这时候老板来了,"小白,今天这么早~待会跟我一起去总部开个会。"

小白:"老板...我能不能带个枕头去啊?"

"提供一个创建产品的接口来负责创建相关或依赖的对象,而不具体明确指定具体类。"这句是设计模式书上的原话,有了这个例子就好理解了,抽象工厂相对于工厂方法来说添加了"组"的概念,就不会出现"火箭筒用步枪子弹这种错误",同时也提高了扩展性,后期要是还出个什么枪套之类的对象,只需要在相应的工厂添加构造方法即可。

写这一个故事也是纪念下通宵的那一晚,哈哈~还有以上代码并没有测试,难免有错,还有对于设计模式的理解仅代表个人观点,假如哪错了或者什么的,请大家纠正指导!

时间: 2024-10-28 10:28:56

设计模式学习之旅——简单工厂、工厂方法、抽象工厂的相关文章

详解设计模式之工厂模式(简单工厂+工厂方法+抽象工厂)

园子里关于23种设计模式的博文已经可以说是成千上万.车载斗量.屯街塞巷.不计其数.数不胜数.摩肩接踵.汗牛充栋.车水马龙.门庭若市.琳琅满目直至让人眼花缭乱了.在这样的大环境下之所以来写设计模式类的博文,并不是像一些"非主流"的爱情观那样"宁缺毋滥". 只是其一呢,因为相当于给自己做一个总结,加深一下自己这方面的认识,因为掌握了和把它写出来我感觉后者还可以对技能有一个提升,其二呢是因为最近公司有一个内部的training需要讲设计模式. v写在前面 在这里呢,需要向

创建和使用解耦——工厂模式详解(工厂方法+抽象工厂)

1.前言 直接new一个对象是最简单的创建对象的方式,但大量出现在业务代码中会带来至少两个问题.1:创建对象的细节直接暴露在业务代码中,修改实现细节必须修改相关的大量客户端代码.2:直接面向具体类型编程,违反了面向接口编程的原则,系统进行扩展时也不得不进行大量修改.要使得系统具有的良好的可扩展性以及后期易于维护,必须实现对产品的获取和对产品的使用解耦.要做到这两点,首先要对客户端代码屏蔽掉创建产品的细节,其次,客户端必须面向产品的抽象编程,利用java的多态特性在运行时才确定具体的产品.而这,正

2 简单工厂模式、工厂模式、抽象工厂模式

简单工厂模式: -----------------------------------Pizza.java-------------------- package com; public abstract class Pizza { public abstract void prepare(); public abstract void bake(); public abstract void cut(); } -----------------------------------APizza.

[Python设计模式] 第15章 如何兼容各种DB——抽象工厂模式

github地址:https://github.com/cheesezh/python_design_patterns 题目 如何让一个程序,可以灵活替换数据库? 基础版本 class User(): """ 用户类,模拟用户表,假设只有ID和name两个字段 """ def __init__(self): self.id = None self.name = None class SqlServerUser(): ""&qu

Delphi 设计模式:《HeadFirst设计模式》Delphi代码---工厂模式之抽象工厂[转]

 1 2 {<HeadFirst设计模式>工厂模式之抽象工厂 } 3 { 抽象工厂的产品                       } 4 { 编译工具:Delphi7.0                  } 5 { E-Mail :[email protected]          } 6 7unit uPizzaIngredient; 8 9interface1011type12  TDough = class(TObject)13  end;1415  TThinCrustDoug

工厂模式[3] 抽象工厂 Abstract Factory

简介 1.简单工厂,或静态工厂,产品接口 定义:专门定义一个类来负责创建其他类的实例,被创建的实例通常具有共同的父类或实现同一接口 优点:客户端可以直接消费产品,而不必关心具体产品的实现(不关心对象的构造方法是怎么new的),消除了客户端直接创建产品对象的责任,实现了对责任的分割. 缺点:工厂类记录了所有产品的创建逻辑,一旦不能正常工作,整个系统都会受到影响:而且当产品种类多.结构复杂的时候,把所有创建工作放进一个工厂中来,会使后期程序的扩展较为困难. 2.工厂方法,工厂接口+产品接口 定义:在

6创建型模式之工厂模式与抽象工厂模式

工厂模式 概念 工厂方法模式同样属于类的创建型模式又被称为多态工厂模式 . 工厂方法模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中. 核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品. 类图角色和职责 抽象工厂(Creator)角色 工厂方法模式的核心,任何工厂类都必须实现这个接口. 具体工厂( Concrete  Creator)角

工厂模式和抽象工厂模式

工厂模式: 定义一个用于创建对象的接口,让他的子类决定实例化哪个类.使类的实例化延迟到子类. 1.普通的工厂模式: public class GoodProduct implements Product { private String prodInfo = "Iam the good prod"; public String getProductInfo() { // TODO Auto-generated method stub return this.prodInfo; } pu

设计模式学习(二)——简单工厂模式、工厂模式、抽象工厂模式

最近抽时间将之前看过的"程序人生"公众号推送的一篇工厂模式的介绍进行了实践,为了加深自己理解,特将自己的学习理解记录于此.初识设计模式,就被设计模式的精妙深深吸引,感觉脱离设计模式的代码就失去了美丽.作为一个测试,平日写代码的机会肯定不如开发多,但是希望自己能通过努力逐步提升代码水平,有一天也能写出优美的代码.如果有对于工厂模式或其他设计模式感兴趣的朋友欢迎一起探讨. 一.简单工厂模式 定义:专门定义一个类用来创建其他类的实例,被创建的实例通常具有共同的父类. 场景一:恰巧今天,老大兴