由浅入深学“工厂模式”(2)

  3.4 工厂方法

有了简单工厂模式后,已经给我们带来了一些好处,但是还存在一些问题,如果我们又多了一个影像家电产品MP4之后,我们可以使MP4类从VideoWiring派生,但是却要修改Create类的代码使它能够生产出MP4这个产品来。不好的地方就在于,我们每次多一个产品的时候都需要修改Create而不是保持原来的代码不修改仅仅进行一种扩展。在Create类中修改不是每次都简单的多一个Case语句就能够解决问题。因为Create类中还封装了创建对象的逻辑,有可能还需要修改这些逻辑。这就违反了面向对象设计中一个很重要的原则“开-闭”原则。

 

“开-闭”原则the Open Closed Principle OCP):

在面向对象设计中,如何通过很小的设计改变就可以应对设计需求的变化,这是令设计者极为关注的问题。开闭原则就是个软件实体在扩展性方面应该是开放的而在更改性方面应该是封闭的。这个原则说的是,在设计一个模块的时候,应当使这个模块可以在不被修改的前提下被扩展。通过扩展已有的软件系统,可以提供新的行为,以满足对软件的新需求,使变化中的软件系统有一定的适应性和灵活性。已有的软件模块,特别是最重要的抽象层模块不能再修改,这就使得变化中的软件系统有一定的稳定性和延续性。因此在进行面向对象设计时要尽量考虑接口封装机制、抽象机制和多态技术。

 

前边设计(简单工厂)中存在的问题就是它分装了创建不同对象的逻辑,当有新的产品的时候不易扩展。在开闭原则的指导下我们考虑如何重新修改前边的设计,我们要尽量使用抽象机制和多态技术。我们放弃对创建不同对象的逻辑的封装,也采用类似产品的方式,抽象出抽象工厂,具体工厂,具体工厂从抽象工厂派生,每个具体工厂中生产一种具体的产品。“太棒了,告诉你,你的这个想法就是工厂方法模式”。

 

下面使用工厂方法模式修改前边的设计:

 sp4.JPG

None.gif public   abstract   class  Create
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
public abstract VideoWiring factory();
ExpandedBlockEnd.gif}

None.gif
None.gif
public   class  DVDCreate: Create 
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
public override VideoWiring factory()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
return new DVD();
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
None.gif
public   class  VCDCreate: Create 
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
public override VideoWiring factory()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
return new VCD();
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

 

VideoWiring、DVD、VCD三个类的代码和前边的相同,下面我们看看在客户端如何使用。

None.gif          private   void  PlayVideo()
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif {
InBlock.gif            VideoWiring dvd,vcd;
InBlock.gif            Create dvdCreate,vcdCreate;
InBlock.gif            dvdCreate
=new DVDCreate();
InBlock.gif            dvd
=dvdCreate.factory();
InBlock.gif            Play(dvd);
InBlock.gif            vcdCreate
=new VCDCreate();
InBlock.gif            vcd
=vcdCreate.factory();
InBlock.gif            Play(vcd);
ExpandedBlockEnd.gif        }

   
下面我们考虑需要扩展一个新的产品MP4的时候如何处理。

sp5.JPG
我们来看看增加的代码:

None.gif public   class  MP4Create: Create 
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
public override VideoWiring factory()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
return new MP4();
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
None.gif
public   class  MP4: VideoWiring 
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
public override string PlayVideo()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
return "正在播放MP4";
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}


我们再看看客户端代码:

None.gif          private   void  PlayVideo()
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif {
InBlock.gif            VideoWiring dvd,vcd;
InBlock.gif            Create dvdCreate,vcdCreate;
InBlock.gif            dvdCreate
=new DVDCreate();
InBlock.gif            dvd
=dvdCreate.factory();
InBlock.gif            Play(dvd);
InBlock.gif            vcdCreate
=new VCDCreate();
InBlock.gif            vcd
=vcdCreate.factory();
InBlock.gif            Play(vcd);
InBlock.gif    
InBlock.gif            
//下面是新增的代码
InBlock.gif
            VideoWiring mp4;
InBlock.gif            Create mp4Create;
InBlock.gif            mp4Create
=new MP4Create();
InBlock.gif            mp4
=mp4Create.factory();
InBlock.gif            Play(mp4);
InBlock.gif
ExpandedBlockEnd.gif        }

None.gif


我们可以看出使用了工厂方法模式后,很好的满足了开闭原则,当我们增加了一个新的产品MP4的时候没有修改原来的代码,而仅仅是对原来的功能进行扩展系统便有了MP4这个产品的功能。

 

将工厂方法模式推广到一般情况:

sp6.JPG
角色说明:

抽象工厂(Creator):定义具体工厂的接口,所有的创建对象的工厂类都必须实现这些接口。

具体工厂(ConcreteCreator):具体工厂包含与应用密切相关的逻辑。复杂创建具体的产品。

抽象产品(Product):所有产品的基类。

具体产品(ConcreteProduct):实现抽象产品申明的接口。工厂方法模式所创建的每个对象都是某个具体产品的实例。

  

工厂方法模式的用意是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类中。工厂方法模式是简单工厂模式的进一步抽象和推广。由于使用了多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点。在工厂方法模式中,核心的工厂类不再负责所有的产品的创建,而是将具体创建的工作交给子类去做。这个核心类则成为了一个抽象工厂角色,仅负责给出具体工厂子类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节。这种进一步抽象化的结果,使这种工厂方法模式可以用来允许系统在不修改具体工厂角色的情况下引进新的产品。

(未完代续)..........

Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、习资料等,我会提供帮助,提供资料,鼓励习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等科竞赛比赛、初期项目立项、习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源习/技术交流/习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值