什么是工厂模式(一秒带你看透这里的秘密)

什么是工厂模式(一秒带你看透这里的秘密)
1.工厂模式具体包括简单工厂、工厂方法和抽象工厂,按从简单到复杂的顺序排列,属于设计模式的创造型,其中简单工厂不属于GOF 23年的模式。但是对于理解其他工厂模式是一个很好的基础,所以很多人在谈到设计模式的时候都会提到工厂方法模式。创建模式侧重于对象的创建。创建模式抽象了创建对象的过程,也可以理解为封装了创建对象的过程。作为客户端程序,它只需要使用对象,不再关心创建对象过程中的逻辑
2不要使用任何模式
我们现在有这样一个设计,视频线路包括DVD和VCD。基类VideoWiring中有一个PlayVideo方法,被子类重载。
怎么才能叫PlayVideo来玩我们可以看到下面的代码是可以实现的。
下面是调用要播放的对象的方法的代码:
公共抽象类视频连线
{
public抽象字符串PlayVideo();
}
公共级VCD:视频布线
{
公共覆盖字符串PlayVideo()
{return ‘立即播放VCD ‘;}
}
公共级DVD:视频布线
{
public override string play video(){ return“立即播放DVD}
}
dvd。PlayVideo();这样的说法。
private void PlayVideo()
{ DVD DVD=new DVD();
消息框。放映(dvd。PlayVideo());
VCD vcd=新VCD();
消息框。秀(VCD。PlayVideo());
}
以上代码可以实现功能,但是不好。为什么类实现了多态,但是我们在调用时不使用多态。如果我们有很多视频家电,我们需要写很多相似之处
下面是使用多态完成播放功能的代码:
private void PlayVideo()
{
视频布线VW;
vw=新DVD();
Play(大众);
vw=新VCD();
Play(大众);
}
私人空间游戏(视频连线大众)
{
字符串str=vw。PlayVideo();
消息框。show(str);
}
无论什么视频家电,我们都可以统一播放,即大众。PlayVideo()。
再来讨论一下上面代码的问题。虽然web上的代码很短,应该没有问题,但是要设定更高的目标,考虑如何达到良好的封装效果,减少错误修改的几率。自然要考虑对象创建的问题,能否让不同视频家电的创建方式相同,创建过程为用户封装,也就是说对象的创建和播放功能一样简单统一。如果能够实现,将会给我们的系统带来更大的可扩展性和尽可能少的修改。“哇!那就好了。”。“不要羡慕,看看工厂方法模式,听说可以实现。”
3工厂方法模式
我们通过使用一个简单的工厂继续改进上面的代码。根据以上分析,我们考虑进一步封装对象创建。类用于封装对象的创建。这个类被称为工厂,因为它有一个单独的函数,所以它一个接一个地生成类。以下是工厂类的示例代码:
公共类创建
{
公共静态视频线路工厂(字符串视频名称)
{
开关(视频名称)
{
case ‘DVD’:返回新DVD();
案例‘VCD’:返回新VCD();
}
返回null
}
}
这样,我们的客户端代码可以更加有效和简洁:
注意:在上面两个代码示例中,我们已经使用了向上转换。一、注意Create类的工厂方法中返回新DVD()的使用;这个说法,但是这个函数的返回值是VideoWiring,是DVD类的基类。这就是为什么我们的客户端程序可以使用语句视频连线VW=create.factory (‘DVD ‘)。这样,客户端程序就不关心创建是如何完成的,创建的对象是什么,就可以调用基类的统一接口来实现它们的功能。用UML来表达如下图所示:
private void PlayVideo()
{
video wiring VW=create . factory(‘ DVD ‘);
大众。PlayVideo();
大众=创造。工厂(‘ VCD ‘);
大众PlayVideo();
}
角色说明:
工厂类(创作者):根据业务逻辑创建具体产品,由客户程序直接调用。
抽象产品(Product):作为具体产品的基类,提供统一的接口,也是工厂类要返回的类型。
具体产品(Concrete Product):工厂类真正要创建的类型。上图中仅仅展示了一个具体产品,有多个产品的时候类似。
下面我们对简单工厂模式进行总结。使用简单工厂的好处是:
1、充分利用了多态性不管什么具体产品都返回抽象产品。 2、充分利用了封装性,内部产品发生变化时外部使用者不会受到影响。
缺点是:如果增加了新的产品,就必须得修改工厂(Factory)。
抽象工厂模式可以向客户端提供一个接口,使得客户端在不必指定产品的具体类型的情况下,创建多个产品族中的产品对象。这就是抽象工厂模式的用意
我们将工厂模式推广到一般的情况,它的类图如下所示:
在有名的OOD的设计原则中有一个叫做里氏代换原则(Liskov Substitution Principle, LSP)。它的实质也就是讲向上转型。它的内容是:任何接收父类型的地方,都应当能够接收子类型,换句话说如果使用的是一个基类的话,那么一定适用于其子类,而且程序察觉不出基类对象和子类对象的区别。LSP是继承复用的基石,只有当派生类可以替换掉基类,软件的功能不受到影响时,基类才能真正被复用
工厂模式属于创建型模式,它提供了一种创建对象的最佳方式。工厂模式关心的是最终产出(创建)的对象, 而不关心创建的过程。举个例子,好比您需要一辆汽车,可以直接从工厂里面提货,而不用去管这辆汽车是怎么做出来的,以及这个汽车里面的具体实现。
平时我们创建对象的时候通常是通过new()的方式,如果我们需要创建对象时做点初始化的工作,比如赋值,我们可能会想到在构造函数中完成,但是有时初始化工作并不是赋值那么简单时,可能会是一段很长的代码,如果写入构造函数中,代码就会显得很难看,而且有悖于Java面向对象的原则,面向对象的封装(Encapsulation)和分派(Delegation)告诉我们,尽量将长的代码分派“切割”成每段,将每段再“封装”起来(减少段和段之间耦合联系性),这样,就会将风险分散,以后如果需要修改,只要更改每段,不会再发生牵一动百的事情。
优点:
(1)给系统带来更大的可扩展性和尽量少的修改量。
(2)一个调用者想创建一个对象,只要知道其名称就可以了。
(3)屏蔽产品的具体实现,调用者只关心产品的接口。
补充:缺点:每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。
(1) new
(2) 通过反射,获得class对象后,我们就可以通过class对象.newInstance()来获得实际对象
详细介绍请查阅 百度经验 —
Spring中通过BeanFactory、ApplicationContext创建Bean对象时使用到了工厂模式。
如果明确了要在不同条件下创建不同实例时就可以使用工厂模式(何时使用)。
使用场景:
1、数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。
2、日志记录器:记录可能记录到本地硬盘或者远程服务器等,用户可以选择记录日志到什么地方。
请查阅 菜鸟教程 —
(1) 为什么要用工厂模式(优点) 为什么不直接用new
(2) spring中哪里用到了工厂模式
(3) 除了Spring,那些场景用到了工厂模式
(4) 实例化对象的方式