我对类工厂模式有了新认识(ActionScript描述)
博客专区 > vimfung 的博客 > 博客详情
我对类工厂模式有了新认识(ActionScript描述)
vimfung 发表于1年前
我对类工厂模式有了新认识(ActionScript描述)
  • 发表于 1年前
  • 阅读 38
  • 收藏 2
  • 点赞 0
  • 评论 0

腾讯云 成都新区开服特惠,热门产品8.5折>>>   

最近在做架构设计研究时忽然地对类工厂模式有了新的认识,因此把自己的一些设计上的心得跟大家分享。希望可以跟大家共同探讨,废话就少说了,直接就进入主题。

    以前一直搞不懂为什么要有类工厂这种设计模式,因为我之前一直认为他仅仅是把一些类对象构造的功能摆在一起,然后通过工厂类来进行构造对象。这种设计很让我费解,因为他不像单例模式、观察者模式那么易懂。不明白使用了类工厂模式这样做的好处到底是什么,虽然一些资料上有说是隐藏了一些类的构造过程,但是如果我直接调用这些类的构造函数和使用工厂类来构造对象的效果还不是一样吗?(以前我是这样想的。呵呵~)

    经过这段时间的学习,我似乎有点懂了。原来我之前一直想不通的原因是在于我把整个软件设计的过程都集中在一个人的身上了,任何功能化模块化的事情都是以自我为中心考虑了。因此体现不出类工厂模式的好处。其实,如果我们的一个软件当中划分了很多个模块,而这些模块都是由不同的人去负责,当某些功能模块需要提供一组数据模型或者工具类,而又不想把具体的实现暴露给其他人知道时,这时候使用类工厂模式是最佳选择。

    为什么呢?因为类工厂隐藏了类的构造过程,并且整个模块里面就只有类工厂是对外公开的访问对象(其他开发人员是没有办法直接调用此模块里面的其他对象的)。其他开发人员只要访问工厂类就能够得到相应的类对象,而不需要关心此模块内部的实现。为了证明此一设计方法的可行性,以下采用ActionScript脚本进行举例说明(以下代码采用ActionScript3语法进行阐述,在Flash Builder下进行实现)。

假如现在我需要设计一个模块提供一组数据模型给其他模块进行调用,这时候我需要创建一个SWC类库,启动Flash Builder新建一ActionScript库项目。假设有ClassA和ClassB两个数据模型类,其定义如下:

//----------------------------------------------------------------------

//ClassA定义

package{

  internal class ClassA extends Object{

    public functionClassA():void{

      _value=1;

    }

    private var_value:int;

    public function get value():int{

      return _value;

    }

    public function set value(value:int):void{

      _value=value;

    }

  }

}

//----------------------------------------------------------------

//ClassB定义

package{

  internal class ClassB extends Object{

    public functionClassB(value:int):void{

      _value=value;

    }

    private var_value:int;

    public function get value():int{

      return _value;

    }

    public functionset value(value:int):void{

      _value=value;

    }

  }

}

    为了能够尽量说明问题,上面定义的ClassA和ClassB都包含一个属性value,而这个value在构造的时候是有所不同的。ClassA是在构造的时候给_value赋上了一个整型值1,而ClassB在构造时是由构造参数来指定_value的值。大家可能已经注意到了,就是ClassA和ClassB的访问权限为internal(包内访问),并不是public(公开)。这样的做法就是为了防止其他调用此库的模块非法访问库中对外隐藏的对象。

数据模型类已经定义完毕,那么开始定义工厂类,其实这里的工厂类要做的事情很简单,就是把ClassA和ClassB生成对象并返回给调用者。因此,类工厂有如下定义:

//--------------------------------------------------------

//类工厂定义

package{

  public class ClassFactory extends Object{

    public functionClassFactory():void{}

    public static functioncreateClassA():ClassA{

      return new ClassA();

    }

    public staticfunction createClassB(value:int):ClassB{

      return new ClassB(value);

    }

  }

}

    上面的工厂类中分别定义了两个静态方法createClassA和createClassB。分别调用这两个方法可以返回ClassA或ClassB对象。

    从上面的例子来看,是否让你的思路清晰了很多呢?不过上面的例子是存在一点问题的,那就是之前定义的ClassA和ClassB的访问权限定义为internal,所以如果在工厂类中直接返回这些对象是不合法的。那么,有什么办法可以解决这样的问题呢?这时候接口的设计能够帮助我们解决这一难题。接口是用于定义一组公开的方法提供给外部调用,使用接口可以很好地实现内外分离的效果。在ActionScript中一个类可以继续一个或一个以上的接口。以下分别定义了IClassA和IClassB接口:

//------------------------------------------------------

//IClassA接口定义

package{

  public interface IClassA{

    public function get value():int;

    public function set value(value:int):void;

  }

}

//---------------------------------------------------

//IClassB接口定义

package{

  public interface IClassB{

    public function get value():int;

  }

}

    上面所写的就是关于ClassA和ClassB的两个接口定义。这里要分享一点小心得,接口定义的属性或方法不一定要跟类定义的属性或者方法相等,接口只要把外界需要调用的方法定义出来即可。上面写的IClassB就是这样的一个例子,他只定义了value的获取方法,并没有定义value属性的设置方法,也就是说ClassB对于外界来说他的value属性是只读的。

接口定义完毕后,那么类和工厂类要作如下的修改(加粗红色为修改部分):

//----------------------------------------------------------------------

//ClassA定义

package{

  internal class ClassA extends Object implements IClassA{

    public functionClassA():void{

      _value=1;

    }

    private var_value:int;

    public function get value():int{

      return _value;

    }

    public function set value(value:int):void{

      _value=value;

    }

  }

}

//----------------------------------------------------------------

//ClassB定义

package{

 internal class ClassB extends Object implements IClassB{

    public functionClassB(value:int):void{

      _value=value;

    }

    private var_value:int;

    public function get value():int{

      return _value;

    }

    public function set value(value:int):void{

      _value=value;

    }

  }

}

//--------------------------------------------------------

//类工厂定义

package{

 public class ClassFactory extends Object{

    public functionClassFactory():void{}

    public staticfunction createClassA():IClassA{

      return new ClassA();

    }

    public staticfunction createClassB(value:int):IClassB{

      return new ClassB(value);

    }

  }

}

    整个SWC的类库设计到此告一段落。我们把源码进行编译生成SWC库。那么在其他地方我们可以直接把这个SWC进行引入,然后就可以调用了。调用的方法也很简单,调用的代码如下所示:

varclsA:IClassA=ClassFactory.createClassA();

varclsB:IClassB=ClassFactory.createClassB(5);

共有 人打赏支持
vimfung
粉丝 58
博文 59
码字总数 85338
作品 4
×
vimfung
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: