zoukankan      html  css  js  c++  java
  • 设计模式之工厂模式

    简单的工厂模式

    我的理解,所谓的简单工厂模式就是在客户端中不会直接实例化对象,例如在控制台应用程序中,我们创建了一个

    public abstract class Food
            {
                // 输出点了什么菜
                public abstract void Print();
            }

    食物的抽象类,然后这个抽象类Food有一个抽象的方法这个方法是交给子类去实现具体的方法,接着我们在这个抽像类中实现两个具体的子类

    /// <summary>
            /// 西红柿炒鸡蛋这道菜
            /// </summary>
            public class TomatoScrambledEggs : Food
            {
                public override void Print()
                {
                    Console.WriteLine("一份西红柿炒蛋!");
                }
            }
    
            /// <summary>
            /// 土豆肉丝这道菜
            /// </summary>
            public class ShreddedPorkWithPotatoes : Food
            {
                public override void Print()
                {
                    Console.WriteLine("一份土豆肉丝");
                }
            }

    然后我们就开始重要的步骤了,声明简单的工厂方法

    /// <summary>
            /// 烧菜方法
            /// </summary>
            /// <param name="type"></param>
            /// <returns></returns>
            public static Food Cook(string type)
            {
                Food food = null;
                // 客户A说:我想吃西红柿炒蛋怎么办?
                // 客户B说:那你就自己烧啊
                // 客户A说: 好吧,那就自己做吧
                if (type.Equals("西红柿炒蛋"))
                {
                    food = new TomatoScrambledEggs();
                }
                // 我又想吃土豆肉丝, 这个还是得自己做
                // 我觉得自己做好累哦,如果能有人帮我做就好了?
                else if (type.Equals("土豆肉丝"))
                {
                    food = new ShreddedPorkWithPotatoes();
                }
                return food;
            }

    在这个工厂方法中我们通过传入简单的字符串我们就可以得到不同的对象,这样的设计方法实现了对象之间解耦和的关系

    static void Main(string[] args)
            {
                // 做西红柿炒蛋
                Food food1 = Cook("西红柿炒蛋");
                food1.Print();
    
                Food food2 = Cook("土豆肉丝");
                food2.Print();
    
                Console.Read();
            }

    在main函数中我们只是做了简单的传入字符串我们就可以的到不同的对象,这就是简单的工厂模式

    简单工厂模式的缺点:就是如果我们有多个具体的子类方法,我们就得在工厂的生成方法中加入多个case判断生成的对象,例如在上述的Cook静态方法中我们就要加入多个switch case的来判断选择要生成的对象了,这样的话就就会变的很冗余了~

    工厂模式

    在工厂模式中我们主要是对上面的静态的Food方法做调整,因为上面也说到,如果我们后期要对方法进行扩展,如果有多个食物的实现方法的话Food方法中将会有多个判断的方法,这样看起来代码就会更改很多,所以接下来我们实现工厂方法模式来解决

    public abstract class Creat
            {
                public abstract Food FoodCreatFactory();
            }
    
            public  class TomatoFcactory : Creat
            {
                public override Food FoodCreatFactory()
                {
                    return new TomatoScrambledEggs();
                }
            }
    
            public  class Tudousi :Creat
            {
                public override Food FoodCreatFactory()
                {
                    return new ShreddedPorkWithPotatoes();
                }
            }

    在这里我们定义了一个生产的Creat用来生成FoodType的工厂,之后我们这里实现了两个工厂一个是TomatoFactory,另一个是TudoushiFactory,这两个工厂重写Food方法用来返回Food类

    在客户端我们只要简单的调用,如下

    Creat FoodCreat = new TomatoFcactory();
    
                Food food = FoodCreat.FoodCreatFactory();
                food.Print();

    变的更简单了,如果我们要增加一个新的Food类的话,我们只需要实现一个新的Food类和工厂就可以很方便的调用了

    现在我们新增一个例子来一份烤鸭吧

    public class duckFactory : Creat
            {
                public override Food FoodCreatFactory()
                {
                    return new duck();
                }
            }
            public class duck : Food
            {
                public override void Print()
                {
                    Console.WriteLine("一份烤鸭!");
                }
            }

    上面我们新增类一个烤鸭工厂和一个烤鸭duck类

    Creat FoodCreat = new duckFactory();
                Food food = FoodCreat.FoodCreatFactory();

    我们只要在客户端简单的如上调用就可以实现了

    抽象工厂模式

    在工厂模式中我们实现类从简单的工厂模式的过渡,解决了创建过多产品过程中增加代码的冗余过程,但是我们上面的工厂模式只能生产一种产品,但是在实际的生活过程中,一个工厂却可以生成多个产品,也就是多元话的工厂,如果代码不进行更改的话,我们也就不能实现多元化的工厂设计模式了,接下来就到抽象工厂模式出现了.

    接下来我们让duckFactory也可生产chicken鸡了

    public abstract class AnimalFactory
            {
                public abstract Food DuckFactory();
                public abstract Food ChickenFactory();
            }
    
            public class Hainai : AnimalFactory
            {
                public override Food DuckFactory()
                {
                    return new HaiNandDuck() ;
                }
                public override Food ChickenFactory()
                {
                    return new HaiNanChicken();
                }
            }
            public class GuangDong : AnimalFactory
            {
                public override Food DuckFactory()
                {
                    return new GuangDongDuck();
                }
                public override Food ChickenFactory()
                {
                    return new GuanzDongChicken();
                }
            }
    
            public class HaiNandDuck : Food
            {
                public override void Print()
                {
                    Console.WriteLine("海南椰子鸭!");
                }
            }
            public class HaiNanChicken : Food
            {
                public override void Print()
                {
                    Console.WriteLine("海南椰子鸡!");
                }
            }
            public class GuangDongDuck : Food
            {
                public override void Print()
                {
                    Console.WriteLine("白斩鸭!");
                }
            }
            public class GuanzDongChicken : Food
            {
                public override void Print()
                {
                    Console.WriteLine("白斩鸡!");
                }
            }

    Animal中定义了DuckFactory、ChickenFactory,而且又定义了两个分别不同的工厂Hainai、GuangDong

    在客户端进行调用

    AnimalFactory animal = new Hainai();
                Food food = animal.ChickenFactory();
                food.Print();

    抽象工厂模式:提供一个创建产品的接口来负责创建相关或依赖的对象,而不具体明确指定具体类

    但是我们也可以看见抽象工厂模式中的缺点,如果下次这个AnimalFactory要增加一种新的产品的话,就要去更改抽象接口中AnimalFactory定义的对象,这样之前继承的子类都将要进行更改,如果这样做就“开发-封闭”原则.

  • 相关阅读:
    常见的Mysql十款高可用方案
    01 . OpenResty简介部署,优缺点,压测,适用场景及用Lua实现服务灰度发布
    08 . Jenkins之SpringCloud微服务+Vue+Docker持续集成
    TomcatAJP文件包含漏洞及线上修复漏洞
    Nginx升级加固SSL/TLS协议信息泄露漏洞(CVE-2016-2183)和HTTP服务器的缺省banner漏洞
    03 . Go开发一个日志平台之Elasticsearch使用及kafka消费消息发送到Elasticsearch
    关于本博客皮肤样式配置
    01 . etcd简介原理,应用场景及部署,简单使用
    Spring Cloud Config
    Spring Cloud Gateway
  • 原文地址:https://www.cnblogs.com/ilooking/p/4307527.html
Copyright © 2011-2022 走看看