当前位置: 首页 > 后端技术 > Java

百度工程师教你玩转设计模式(工厂模式)

时间:2023-04-01 18:33:24 Java

作者|PolarisGroup要想写出好的代码,设计模式(DesignPattern)是必备的基本功,而设计模式是面向对象设计(ObjectOrientedDesign)中反复出现的问题的解决方案,本文介绍工厂模式(工厂模式)。工厂模式属于创建模式(BuilderPattern),它提供了创建对象的最佳方式。创建对象时,对象的创建逻辑不暴露给客户端,而是使用一个通用的接口创建对象。工厂模式应用的典型场景是你希望能够创建一个对象,但是创建过程比较复杂,你希望对外界隐藏这些细节,例如:对象可能创建在一个池中,并非每次都凭空创造一个新的;创建对象时,有很多参数决定了如何创建对象;创建对象具有复杂的依赖关系。在实现方式上,主要有简单工厂模式、工厂方法模式和抽象工厂模式。一、简单工厂模式在文档解析场景中的应用在日常开发场景中,如果要创建的产品(要创建的对象类)不多,只需要一个工厂类就可以完成。这种模式被称为“简单工厂模式”。使用简单工厂模式的客户端(具体调用者)只需要传入需要创建产品类的参数,无需关心对象如何创建的逻辑,可以轻松创建出想要的产品。以Word2007类型文档解析场景为例:文档主体在document.xml文件中,解析时根据内容结构维度创建具体的Paragraph、Table、Draw等解析类。在解析过程中,如果直接构造解析类对应的对象,两者之间的耦合度会太重。您可以使用“简单工厂模式”将解析类的实际创建推迟到工厂类。这也满足了创作模式所要求的“创作与使用分离”的特点。具体实现包括以下几个部分:简单工厂(SimpleFactory):它是简单工厂模型的核心,负责实现创建所有具体Parser实例的内部逻辑。抽象产品(Product):是简单工厂创建的所有对象的父类,负责描述所有Parser实例共享的公共接口。具体产品(ConcreteProduct):是简单工厂模式的创建对象,负责创建具体的解析类。publicclassDocxPaser{//抽象产物:所有解析器共享的公共接口publicinterfaceIPaser{voidprocess(stringentity);}//具体产品:ParagraphParserstaticclassParagraphimplementsIPaser{publicvoidprocess(stringentity){System.out.println("解析段落...");}}//具体产品:TableParserstaticclassTableimplementsIPaser{publicvoidprocess(stringentity){System.out.println("ParseTable...");}}//具体产品:DrawParserstaticclassDrawimplementsIPaser{publicvoidprocess(stringentity){System.out.println("ParseDraw...");}}finalclassConst{staticfinalintENTITY_PARAGRAPHP=0;staticfinalintENTITY_TABLE=1;staticfinalintENTITY_DRAW=2;}//简单工厂:负责实现创建所有具体Parser实例的内部逻辑staticclassParserFactory{publicstaticIPasercreatParser(intkind){switch(kind){caseConst.ENTITY_PARAGRAPHP:returnnewParagraph();caseConst.ENTITY_TABLE:returnnewTable();caseConst.ENTITY_DRAW:returnnewDraw();}返回空值;}}//简单使用示例publicstaticvoidmain(String[]args){//实体对应document.xml,这里省略具体的获取过程...//解析段ParserFactory.creatParser(Const.ENTITY_PARAGRAPHP)。process(entity)//解析表ParserFactory.creatParser(Const.ENTITY_TABLE).process(entity)//解析绘制ParserFactory.creatParser(Const.ENTITY_DRAW).process(entity)...}}二、工厂的应用简单工厂模式中自动化测试场景中的方法模式,调用者只需要传入要创建的对象类的参数就可以得到一个需要的对象,而不用关心对象的具体创建细节。当需要创建的对象种类较少,以后不再容易增加时,就简单了。工厂模式可以满足要求。但是对于需要创建的对象类型较多,后续变化频繁的场景,简单工厂模式有两个明显的问题:因为以后每次添加一个对象,工厂类中的判断逻辑都需要被修改,违反了代码设计方法中的开闭原则,需要对输入参数进行判断,然后初始化相应的类。简单工厂类中if-else或者switch-case分支太多,代码比较臃肿。为了解决以上问题,可以选择工厂方法模式:定义一个创建对象的接口,然后实现创建不同对象的子类,对象的初始化由各个工厂的子类完成。他和简单工厂的区别在于:开闭原则:在添加对象的情况下,简单工厂模式下需要修改工厂类,而工厂方法模式只需要添加一个子类即可工厂完成新对象的初始化。能。代码简洁:简单工厂通过参数选择和初始化子类,所有工作都由工厂类完成。工厂方法只是定义了创建对象的接口,对象的创建是在子类中实现的。以前端浏览器自动化测试场景为例,在不同的浏览器场景下,必须使用相应的浏览器驱动来完成测试执行,比如常见的Chrome、Firefox、Safari、IE浏览器。这个场景可以通过工厂方法模式来实现。首先是在场景中定义驱动对象。Driver是每个具体驱动需要继承的抽象类,其他XDriver是具体浏览器的驱动对象。接下来,定义相应的抽象工厂,实现工厂子类,用于不同的对象初始化。AbstractFactory是一个抽象工厂,它定义了创建驱动程序对象的接口。其他每个工厂都实现了抽象工厂的接口,并提供相应驱动程序的初始化能力。最后,实际用户可以根据需要选择某个工厂类来完成相应的驱动初始化。publicclassFactoryDe??mo{//抽象对象:所有驱动对象的公共父类abstractstaticclassDriver{abstractvoidprocess();}//具体驱动对象:Chrome浏览器驱动对象staticclassChromeDriverextendsDriver{@Overridevoidprocess(){System.out.println("ChromeDriverprocess");//dosomething}}//具体驱动对象:Firefox浏览器驱动对象staticclassFirefoxDriverextendsDriver{@Overridevoidprocess(){System.out.println("FirefoxDriverprocess");//做一些事情}}//具体的驱动对象:Safari浏览器驱动对象staticclassSafariDriverextendsDriver{@Overridevoidprocess(){System.out.println("SafariDriverprocess");//dosomething}}//抽象工厂中所有工厂的公共接口publicinterfaceAbstractFactory{Drivercreate();}//具体工厂:负责创建Chrome浏览器驱动对象staticclassChromeDriverFactoryimplementsAbstractFactory{@OverridepublicDrivercreate(){返回新的ChromeDriver();}}//具体工厂:负责创建Firefox浏览器驱动对象staticclassFirefoxDriverFactoryimplementsAbstractFactory{@OverridepublicDrivercreate(){returnnewFirefoxDriver();}}//具体工厂:负责创建Safari浏览器驱动对象staticclassSafariDriverFactoryimplementsAbstractFactory{@OverridepublicDrivercreate(){returnnewSafariDriver();}}publicstaticvoidmain(String[]args){//创建一个Chrome驱动程序对象AbstractFactorychromeDriverFactory=newChromeDriverFactory();驱动程序chromeDriver=chromeDriverFactory.create();chromeDriver.process();//创建Firefox驱动程序对象AbstractFactoryfirefoxDriverFactory=newFirefoxDriverFactory();();//...}}三、抽象工厂模式在跨端场景的应用。抽象工厂模式是工厂方法模式的进一步深化。在工厂方法模式中,只有一个抽象方法,如果要实现多种不同的类对象,只能创建具体工厂方法的不同子类来实现,而抽象工厂就是让一个工厂负责创建多个不同类型的对象在一个典型的以跨端场景为例。用户可以购买的会员类型有很多种。各类会员在iOS、Android、PC下的权益页面略有不同,实例化过程非常复杂。如果不使用工厂模式,需要在需要实例的地方都需要编写复杂的实例化代码。修改实例化过程时,每次都要修改,维护成本非常高。如果使用简单工厂模式或工厂方法模式代替抽象工厂模式,则需要为每个类型成员实现三个工厂,不易维护。在这种场景下,我们可以使用抽象工厂模型来解决问题,编写抽象工厂和成员抽象类,针对iOS、Android、PC分别实现三个具体的工厂,根据场景选择具体的工厂获取成员实例。//抽像产品publicinterfaceVip{}//实体产品publicclassNormalVipimplementsVip{}//普通会员publicclassMonthlyVipimplementsVip{}//包月会员publicclassIOSNormalVipextendsNormalVip{}publicclassAndroidNormalVipextendsNormalVip{}publicclassPCNormalVipextendsNormalVip{}publicclassIOSMonthlyVipextendsMonthlyVip{}publicclassAndroidMonthlyVipextendsMonthlyVip{}publicclassPCMonthlyVipextendsMonthlyVip{}//抽像工厂publicinterfaceAbstractVipFactory{VipcreateNormalVip();VipcreateMonthlyVip();}//实体工厂publicclassIOSVipFactoryimplementsAbstractVipFactory{@OverridepublicVipcreateNormalVip(){returnnewIOSNormalVip();}@OverridepublicVipcreateMonthlyVip(){返回新的IOSMonthlyVip();}}...//调用示例publicclassClient{publicstaticvoidmain(String[]args){IOSVipFactoryiosVipFactory=newIOSVipFactory();VipiosNormalVip=iosVipFactory.createNormalVip();}}四、总结语通过以上三个实际案例的讲解和具体代码的阅读,大家应该对工厂模式的应用场景和具体实现方案有更深入的了解。结合以上三种情况的分析,当创建过程复杂时,适合使用工厂模式,常用的工厂模式有:简单工厂模式:当实例化过程复杂时,可以选择工厂方法模式:当产品结构复杂时,可以选择抽象工厂模式:当产品类型和结构较多时,可以选择----------END----------推荐阅读【技术加油站】系列:揭秘百度智能测试在测试分析领域的实践百度用户产品流批量集成实时数据仓库实践ffplay视频播放原理分析百度工程师眼中的云原生可观察性跟踪技术使用百度开发者工具4.0打造专属小程序IDE百度工程师教你玩转设计模式(观察者模式)