博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
工厂模式
阅读量:6677 次
发布时间:2019-06-25

本文共 6015 字,大约阅读时间需要 20 分钟。

工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。

工厂模式可以分为三类:

1)简单工厂模式(Simple Factory)

2)工厂方法模式(Factory Method)
3)抽象工厂模式(Abstract Factory)

简单工厂模式我们也可以理解为负责生产对象的一个类, 我们平常编程中,当使用"new"关键字创建一个对象时,此时该类就依赖与这个对象,也就是他们之间的耦合度高,当需求变化时,我们就不得不去修改此类的源码,此时我们可以运用面向对象(OO)的很重要的原则去解决这一的问题,该原则就是——封装改变,既然要封装改变,自然也就要找到改变的代码,然后把改变的代码用类来封装,这样的一种思路也就是我们简单工厂模式的实现方式了。 

自己做饭,如果我们想吃别的菜时,此时就需要去买这种菜和洗菜这些繁琐的操作,有了餐馆(也就是简单工厂)之后,我们就可以把这些操作交给餐馆去做,此时消费者(也就是我们)对菜(也就是具体对象)的依赖关系从直接变成的间接的,这样就是实现了面向对象的另一个原则——降低对象之间的耦合度。

简单工厂模式又称静态工厂方法模式。重命名上就可以看出这个模式一定很简单。它存在的目的很简单:定义一个用于创建对象的接口。

先来看看它的组成:
1) 工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑,用来创建产品
2) 抽象产品角色:它一般是具体产品继承的父类或者实现的接口。
3) 具体产品角色:工厂类所创建的对象就是此角色的实例
在这里插入图片描述

class Program    {        static void Main(string[] args)        {            Factory.CreatFood("土豆");            Console.ReadKey();        }    }    //工厂类    public class Factory    {        //生产食物        public  static Food CreatFood(string foodName)        {            Food food = null;            if (foodName.Equals("土豆"))            {                food=new Potato();                food.food();            }            else if (foodName.Equals("鸡蛋"))            {                food = new Egg();                food.food();            }            return food;        }    }    //食物基类    public abstract class Food    {        public abstract void food();    }    //土豆    public class Potato : Food    {        public override void food()        {            Console.WriteLine("potato");        }    }    //鸡蛋    public class Egg : Food    {        public override void food()        {            Console.WriteLine("egg");        }    }

简单工厂模式解决了客户端直接依赖于具体对象的问题,客户端可以消除直接创建对象的责任,而仅仅是消费产品。简单工厂模式实现了对责任的分割。

简单工厂模式也起到了代码复用的作用,因为之前的实现(自己做饭的情况)中,换了一个人同样要去在自己的类中实现做菜的方法,然后有了简单工厂之后,去餐馆吃饭的所有人都不用那么麻烦了,只需要负责消费就可以了。此时简单工厂的烧菜方法就让所有客户共用了。(同时这点也是简单工厂方法的缺点——因为工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都会受到影响,也没什么不好理解的,就如事物都有两面性一样道理)
虽然上面已经介绍了简单工厂模式的缺点,下面还是总结下简单工厂模式的缺点:

工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都会受到影响(通俗地意思就是:一旦餐馆没饭或者关门了,很多不愿意做饭的人就没饭吃了)

系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,这样就会造成工厂逻辑过于复杂。
了解了简单工厂模式之后的优缺点之后,我们之后就可以知道简单工厂的应用场景了:

当工厂类负责创建的对象比较少时可以考虑使用简单工厂模式

客户如果只知道传入工厂类的参数,对于如何创建对象的逻辑不关心时可以考虑使用简单工厂模式

工厂方法模式之所以可以解决简单工厂的模式,是因为它的实现把具体产品的创建推迟到子类中,此时工厂类不再负责所有产品的创建,而只是给出具体工厂必须实现的接口,这样工厂方法模式就可以允许系统不修改工厂类逻辑的情况下来添加新产品,这样也就克服了简单工厂模式中缺点

工厂方法模式去掉了简单工厂模式中工厂方法的静态属性,使得它可以被子类继承。这样在简单工厂模式里集中在工厂方法上的压力可以由工厂方法模式里不同的工厂子类来分担。
工厂方法模式组成:
1)抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。
2)具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。
3)抽象产品角色:它是具体产品继承的父类或者是实现的接口。

工厂方法模式使用继承自抽象工厂角色的多个子类来代替简单工厂模式中的“上帝类”。正如上面所说,这样便分担了对象承受的压力;而且这样使得结构变得灵活 起来——当有新的产品产生时,只要按照抽象产品角色、抽象工厂角色提供的合同来生成,那么就可以被客户使用,而不必去修改任何已有 的代码。可以看出工厂角色的结构也是符合开闭原则的!

工厂方法模式仿佛已经很完美的对对象的创建进行了包装,使得客户程序中仅仅处理抽象产品角色提供的接口,但使得对象的数量成倍增长。当产品种类非常多时,会出现大量的与之对应的工厂对象,这不是我们所希望的。

在这里插入图片描述

class Program    {        static void Main(string[] args)        {            Factory factory=new FactoryEgg();            factory.CreatFood();            Console.ReadKey();        }    }    //工厂类    public  abstract class Factory    {        //生产食物        public abstract Food CreatFood();    }    public class FactoryPotato : Factory    {        public override Food CreatFood()        {           Food food=new Potato();            food.food();            return food;        }    }    public class FactoryEgg : Factory    {        public override Food CreatFood()        {            Food food = new Egg();            food.food();            return food;        }    }    //食物基类    public abstract class Food    {        public abstract void food();    }    //土豆    public class Potato : Food    {        public override void food()        {            Console.WriteLine("potato");        }    }    //鸡蛋    public class Egg : Food    {        public override void food()        {            Console.WriteLine("egg");        }    }工厂方法模式是为了克服简单工厂模式的缺点而设计出来的,简单工厂模式的工厂类随着产品类的增加需要增加额外的代码),而工厂方法模式每个具体工厂类只完成单个实例的创建,所以它具有很好的可扩展性。但是在现实生活中,一个工厂只创建单个产品这样的例子很少,因为现在的工厂都多元化了,一个工厂创建一系列的产品,如果我们要设计这样的系统时,工厂方法模式显然在这里不适用,然后抽象工厂模式却可以很好地解决一系列产品创建的问题,这是本专题所要介绍的内容。抽象工厂允许客户使用抽象的接口来创建一组相关产品,而不需要知道或关心实际生产出的具体产品是什么。这样客户就可以从具体产品中被解耦。下面通过抽象工模式的类图来了解各个类中之间的关系:

在这里插入图片描述

抽象工厂模式将具体产品的创建延迟到具体工厂的子类中,这样将对象的创建封装起来,可以减少客户端与具体产品类之间的依赖,从而使系统耦合度低,这样更有利于后期的维护和扩展,这真是抽象工厂模式的优点所在,然后抽象模式同时也存在不足的地方。下面就具体看下抽象工厂的缺点(缺点其实在前面的介绍中以已经涉及了):抽象工厂模式很难支持新种类产品的变化。这是因为抽象工厂接口中已经确定了可以被创建的产品集合,如果需要添加新产品,此时就必须去修改抽象工厂的接口,这样就涉及到抽象工厂类的以及所有子类的改变,这样也就违背了“开发——封闭”原则。知道了抽象工厂的优缺点之后,也就能很好地把握什么情况下考虑使用抽象工厂模式了,下面就具体看看使用抽象工厂模式的系统应该符合那几个前提:一个系统不要求依赖产品类实例如何被创建、组合和表达的表达,这点也是所有工厂模式应用的前提。这个系统有多个系列产品,而系统中只消费其中某一系列产品系统要求提供一个产品类的库,所有产品以同样的接口出现,客户端不需要依赖具体实现。

class Program

{
static void Main(string[] args)
{
Factory factory=new NanchangFactory();
factory.Creatyabo();
factory.Creatyajia();

Console.ReadKey();    }}//工厂基类类public  abstract class Factory{           public abstract  YaBo Creatyabo();    public abstract YaJia Creatyajia();}public class ShanghaiFactory : Factory{    public override YaBo Creatyabo()    {        shanghaiYabo yabo=new shanghaiYabo();        yabo.food();        return yabo;    }    public override YaJia Creatyajia()    {        shanghaiYaJia yaJia=new shanghaiYaJia();        yaJia.food();        return yaJia;    }}public class NanchangFactory : Factory{    public override YaBo Creatyabo()    {        nanchangYabo yabo=new nanchangYabo();        yabo.food();        return yabo;    }    public override YaJia Creatyajia()    {        nanchangYaJia yaJia=new nanchangYaJia();        yaJia.food();        return yaJia;    }}//鸭脖基类public abstract class YaBo{    public abstract void food();}//鸭架基类public abstract class YaJia{    public abstract void food();}public class shanghaiYabo : YaBo{    public override void food()    {        Console.WriteLine("上海鸭脖");    }}public class shanghaiYaJia : YaJia{    public override void food()    {        Console.WriteLine("上海鸭架");    }}public class nanchangYabo : YaBo{    public override void food()    {        Console.WriteLine("南昌鸭脖");    }}public class nanchangYaJia : YaJia{    public override void food()    {        Console.WriteLine("南昌鸭架");    }}

转载地址:http://bcrxo.baihongyu.com/

你可能感兴趣的文章
Java并发和并行的区别
查看>>
extjs down 的用法
查看>>
layabox基础:hello world
查看>>
ClassUtil
查看>>
Elastic-Job定时任务
查看>>
真实分享记录我学习Linux系统遇到的问题
查看>>
Linux下查找占用内存最多的进程
查看>>
mongodb 配置文件
查看>>
查看 docker 容器使用的资源
查看>>
Jedis的配置和优化
查看>>
layui + 阿里巴巴iconfont图标库导入
查看>>
2017总结一
查看>>
MySQL中TIMESTAMPDIFF和TIMESTAMPADD函数的用法
查看>>
Power Designer数据库建模工具,正向、逆向工程
查看>>
Libevent学习-02:搭建CentOS下的开发环境
查看>>
yum install 与 yum groupinstall 的区别
查看>>
Go基础系列:读取标准输入(一)
查看>>
PHP协程入门详解
查看>>
Java_Reflect_1
查看>>
HTML中的<table>标签及其子元素标签,JS中DOM对<table>的操作
查看>>