工厂方法模式(Factory method pattern)
创建一个对象常常需要复杂的过程,所以不适合在一个复杂的对象中。创建对象可能会导致大量的重复代码,也可能提供不了足够级别的抽象。工厂方法模式通过定义一个单独的创建对象的方法来解决这些问题,由子类实现这个方法来创建具体类型的对象。
- //几个Button类
- class Button{/* ...*/}
- class WinButton extends Button{/* ...*/}
- class MacButton extends Button{/* ...*/}
-
- //它们的工厂类
- interface ButtonFactory{
- abstract Button createButton();
- }
- class WinButtonFactory implements ButtonFactory{
- Button createButton(){
- return new WinButton();
- }
- }
-
- class MacButtonFactory implements ButtonFactory{
- Button createButton(){
- return new MacButton();
- }
- }
在JS中创建对象会习惯的使用 new 关键字和类构造函数(当然主要还是对象字面量),问题在于这样会导致两个类之间产生依赖性。
工厂模式就是一种有助于消除两个类依赖性的模式。
简单工厂模式:使用一个类(通常为单体)来生成实例。
复杂工厂模式:使用子类来决定一个成员变量应该是哪个具体的类的实例。
实现1:简单工厂模式
上 JS设计模式 上的实例, 对于自行车商店出售自行车:
- /* BicycleShop class */
- var BicycleShop = function(){};
- BicycleShop.prototype = {
-
- sellBicycle : function( model ){
- var bicycle;
- switch( model ){
- case "The Speedster":
- bicycle = new Speedster();
- break;
- case "The Lowrider":
- bicycle = new Lowrider();
- break;
- case "The Cruiser":
- default:
- bicycle = new Cruiser();
- break;
- }
- return bicycle;
- }
- }
sellBicycle 方法根据所提供的自行车型号来进行自行车的实例创建。那么对于一家ABC店铺,需要Speedster车型我只需要
var ABC = new BicycleShop();
var myBike = ABC.sellBicycle("The Speedster");
以上方式很管用,但是一旦说我需要添加一些自行车款式的时候我就必须修改 BicycleShop 的 switch 部分,那么只要是修改就有可能带来BUG。所以,将这部分生成实例的代码单独的提出来分工交给一个简单的工厂对象是一个很不错的方法。
- var BicycleFactory = {
- createBicycle : function( model ){
- var bicycle;
- switch( model ){
- case "The Speedster":
- bicycle = new Speedster();
- break;
- case "The Lowrider":
- bicycle = new Lowrider();
- break;
- case "The Cruiser":
- default:
- bicycle = new Cruiser();
- break;
- }
- return bycicle;
- }
- }
BicycleFactory 是一个脱离于BicycleShop的单体。降低耦合度的效果显而易见。当需要添加新的类型的时候,不需要动 BicycleShop 只需修改工厂单体对象就可以。
- var BicycleShop = function(){};
-
- BicycleShop.prototype = {
- sellBicycle : function( model ){
- var bicycle = BicycleFactory.createBicycle(model);
- return bicycle;
- }
- }
以上就是一个很好的 简单工厂模式 的实例。该模式将成员对象的创建工作交给一个外部对象实现,该外部对象可以是一个简单的命名空间,也可以是一个类的实例。
实现2:工厂模式
比如加入BicycleShop可以决定从那一家厂商进行进货,那么简单的一个BicycleFactory是不够了的,因为各个厂商会各自生产不同的Speedster,Lowrider,Cruiser等型号自行车,所以首先需要生成各自厂商的shop实例,不同厂商的shop实例拥有不同的生成几个型号自行车的方法。
也就是相当于将自行车对象的实例化推迟到了shop实例中产生。
基础:
- var BicycleShop = function(){}
-
- BicycleShop.prototype={
- sellBicycle: function( model ){
- var bicycle = this.createBicycle( model );
- return bicycle;
- },
- createBicycle: function( model ){
- throw new Error( " Unsupported " );
- }
- }
各自厂商:
- var AcmeBicycleShop = function(){};
-
- extend( AcmeBicycleShop , BicycleShop );
- AcmeBicycleShop.prototype.createBicycle = function( model ){
- var bicycle;
- switch( model ){
- case "The Speedster":
- bicycle = new AcmeSpeedster();
- break;
- case "The Lowrider":
- bicycle = new AcmeLowrider();
- break;
- case "The Cruiser":
- default:
- bicycle = new AcmeCruiser();
- break;
- }
- return bicycle;
- }
-
- var GeneralBicycleShop = function(){};
-
- extend( GeneralBicycleShop , BicycleShop );
- GeneralBicycleShop.prototype.createBicycle = function( model ){
- ...
- }
那么接下来就很简单 对于来自 Acme 进货的
var acmeShop = new AcmeBicycleShop();
var newBicycle = acmeShop.sellBicycle("The Speedster");
当然,你也可以对于外层生成的子类实例在使用简单工厂模式进行包装一下~对于添加其他厂商也很简单,在创建一个Bicycle的子类重新定义其createBicycle的工厂方法即可。
工厂模式使用场合
例如自行车的例子,创建一些用不同方式实现统一接口的对象,那么可以使用一个工厂方法或者简单工厂对象来简化实现过程。选择可以是明确进行的也可以是隐含的。
2. 节省设置开销
如果对象要进行复杂的并且彼此相关的设置的时候,那么工厂模式可以很显著的减少每种对象的代码量。将特定的设置代码提取出来会使得代码有极大地提升。并且能优化结构便于维护。
3. 用于许多小型对象组成一个大对象。
4. 工厂模式之利
主要好处就是可以消除对象间的耦合,通过使用工程方法而不是new关键字。将所有实例化的代码集中在一个位子防止代码重复。
5. 工厂模式之弊
大多数类最好使用new关键字和构造函数,可以让代码更加简单易读。而不必去查看工厂方法来知道。