JavaScript设计模式:工厂模式(附接口模式代码)

傷城~ 2022-06-17 01:23 328阅读 0赞

工厂模式目的:消除类之间的依赖性。
在引入工厂模式以前,我们先给出接口类的代码:

  1. var Interface = function(name,methods){
  2. if(arguments.length != 2){
  3. throw new Error("expect 2 arguments.");
  4. }
  5. this.name = name;
  6. this.methods = [];
  7. if(!methods instanceof Array){
  8. throw new Error("expect the second argument be an Array.");
  9. }else{
  10. methods.forEach(function(method){
  11. if(typeof method != "String"){
  12. throw new Error("expect the second argument be an Array of String.");
  13. }
  14. this.methods.push(method);
  15. });
  16. }
  17. }
  18. Interface.ensureInplements = function(object){
  19. if(arguments.length < 2){
  20. throw new Error("expect 2 or more arguments.");
  21. }
  22. for(var i = 1, len = arguments.length ; i<len ; i++){
  23. var interface = arguments[i];
  24. if(interface.constructor != Interface){
  25. throw new Error("the arguments must be instances of Interface");
  26. }
  27. for(var j=0,methodsLen=interface.methods.length;j<methodsLen;j++){
  28. var methods = interface.methods[j];
  29. if(!object[methods] || typeof object[methods] !== "function"){
  30. throw new Error("methods was not found.");
  31. }
  32. }
  33. }
  34. }

接口类就是为了保证某些对象一定都具有某些方法,可以用Interface.ensureInplements验证。例如,我们想验证car对象是不是Car接口的实例,可以这样写:

  1. Interface.ensureInplements(car,Car);

Car接口可以通过new Interface(“Car”,[“drive”,”ring”…]);这样的形式定义其必须的方法。
这样在通过了Interface.ensureInplements(car,Car);方法后,我们就能保证car对象也拥有方法drive,ring…

简单工厂

直接上栗子比较好:比如说,你想开一家花店,出售各种鲜花:

  1. var FlowerShop = function(){ };
  2. FlowerShop.prototype.sellFlowers = function(name){
  3. var flower;
  4. switch(name){
  5. case 'rose':
  6. flower = new Rose();
  7. break;
  8. case 'lily':
  9. flower = new Lily();
  10. break;
  11. default:
  12. flower = new NormalFlower();
  13. }
  14. Interface.ensureInplements(flower,Flower);
  15. flower.watering();
  16. flower.prune();
  17. return flower;
  18. }
  19. // Flower Interface
  20. var Flower = new Interface("Flower",["watering","prune"...]);

这样,如果我们想要玫瑰花,就:

  1. var newFlowerShop = new FlowerShop();
  2. var rose = newFlowerShop.sellFlowers("rose");

但是,如果你想要为你的花店新加入一种花呢?你就要改写FlowerShop类,即便是这个类的基本功能其实并没有改变:创建鲜花,把花洗干净,修剪,然后返回给客户。

更好的方式是把创建鲜花实例这部分代码交给一个工厂对象。

  1. var FlowerFactory = {
  2. createFlower : function(name){
  3. var flower;
  4. switch(name){
  5. case 'rose':
  6. flower = new Rose();
  7. break;
  8. case 'lily':
  9. flower = new Lily();
  10. break;
  11. default:
  12. flower = new NormalFlower();
  13. }
  14. Interface.ensureInplements(flower,Flower);
  15. return flower;
  16. }
  17. }

FlowerFactory这个对象可以作为一个单体,用来把createFlower方法封装在一个命名空间中,这个方法返回的flower对象实现了Flower接口。这样,我们的花店代码就可以改为:

  1. var FlowerShop = function(){ };
  2. FlowerShop.prototype.sellFlowers = function(name){
  3. var flower = FlowerFactory.createFlower("rose");
  4. flower.watering();
  5. flower.prune();
  6. return flower;
  7. }

工厂模式

真正的工厂模式和简单的工厂模式的区别在于,它不是另外使用一个类,而是使用一个子类来实现对象的创建。
工厂模式的正式定义是:将其成员对象的实例化推迟到子类来实现的类。也就是说,前面的FlowerShop应该作为一个抽象类,真正的实现需要其子类来完成。比如,我们可以创建一个北京花店,出售各种花,也可以再创建一个上海花店,等等。具体对花的实例化代码应该在子类(例如北京花店)中完成。

对FlowerShop的一般性操作应该写在FlowerShop中,而其他个性的代码则被分配到子类中。

发表评论

表情:
评论列表 (有 0 条评论,328人围观)

还没有评论,来说两句吧...

相关阅读