工厂模式杂谈&java的迭代器

转载自http://blog.csdn.net/qq_28241149/article/details/78581200

在java开发中,创建并初始化对象是再平常不过的一件事了,大部分情况下,我们都会选择用new构造符去创建一个新的对象,但是在开发中我们也常常会遇到一些特殊的初始化方式,随举一例,比如在hibernate中,创建session并不是用new构造符去初始化的,往往我们会从sessionFactory实例中去获取session,而这种通过factory获取实例的初始化方式,我们称为工厂模式。


事实上工厂模式是可以细分成好多种类的,有“简单工厂模式”、“工厂方法模式”、“抽象工厂模式”,在G4整理的设计模式中也将工厂方法和抽象工厂分为两种不同的模式,关于这三种模式之间的区别,我借用网上一篇博客来说明:


博客地址:https://www.cnblogs.com/zhangchenliang/p/3700820.html


具体的讲解和例子请自行去阅读这篇博客,这篇博客以一个相对比较通俗易懂的例子来说明了一下几种模式的区别,这里我稍微概述一下。


简单工厂模式是工厂模式的最基本实现,工厂模式原本就是想要把创建实例的过程从调用方抽离出来,简单工厂模式就是把每个需要创建实例对象的类都设置一个创建实例的方法,调用方去调用这些方法。

  1. public class Factory {  
  2.   
  3.     public Object1 create1() {  
  4.         return new Object1();  
  5.     }  
  6.       
  7.     public Object2 create2() {  
  8.         return new Object2();  
  9.     }  
  10. }  
public class Factory {

	public Object1 create1() {
		return new Object1();
	}
	
	public Object2 create2() {
		return new Object2();
	}
}


但是这样的弊端是,万一我想加个Object3,就不得不去修改factory类,为了应对这个方式,就在简单工厂上加上了接口声明多态实现的过程。

  1. public interface Factory<T> {  
  2.   
  3.     public T create();  
  4.       
  5. }  
public interface Factory<T> {

	public T create();
	
}

  1. public class Factory1 implements Factory<Object1> {  
  2.   
  3.     @Override  
  4.     public Object1 create() {  
  5.         return new Object1();  
  6.     }  
  7.   
  8. }  
public class Factory1 implements Factory<Object1> {

	@Override
	public Object1 create() {
		return new Object1();
	}

}

这样当需要加入Object3时就只需要重新写个Factory3去实现Factory接口即可。


但是这样是类族相对比较单一的时候,万一类的继承比较复杂,如何设计这个工厂类,是每个实例都创建一个工厂还是给类族归类去创建一个层次上的工厂,这就是工厂方法模式到抽象工厂模式的进阶。(这个就不举例了,看上面那个链接的博客去吧)


好,现在开始进入正文,首先先来谈谈我对工厂模式的看法。


在网上各种博客中,对工厂模式褒贬不一,有些人认为引用创建本来就是调用方的职责,将这个过程从调用方抽离不符合高内聚的原则;也有人认为,如果一个类的new构造符被大量的使用,在这个时候被调用方想要修改创建的逻辑就会非常被动,所以抽离出来降低了耦合性。


其实我个人觉得这两种说法都不是非常妥当,首先前一种说法过分钻牛角尖,工厂模式并不是否定用new构造符去创建对象的可行性,而是在一些情况下,用new构造符去创建会有大量的其他工作,对于调用方来说是个比较繁复的工作,比方说前文提到的hibernate的sessionFactory,它完成了数据源的初始化,并创建数据库操作的session,相比之下如果要由调用方自己去new一个session,再从静态变量中获取DataSource传给session,这个过程的复杂程度远高于用工厂模式,因此用工厂模式并没有降低内聚,反而在某些情况下降低了耦合。


而后一种论调的问题在于,忽略了工厂模式在抽象化上的作用。事实上如果单纯依照这种看法,我们大可以在构造函数中完成逻辑的变更,如果是传入参数发生变化,用工厂模式也很难起到很好的作用;个人认为工厂模式在多方调用中一个更大的优势就是其抽象性,尤其是工厂方法模式,当你已经得到一个工厂的时候,无需知道需要创建的实例本身是个啥,只需要用这个工厂去创建实例即可。


这个论点乍一看好像很扯淡,因为在工厂方法模式中,如果你都已经去确定工厂到底是哪一个了,这和确定需要创建的实例究竟是哪个类有什么区别?起初我也是这么认为的,直到看到一个观点,java集合类的iterator方法就是一个工厂模式,我才恍然大悟。


在java的集合类接口Collection中,定义了一个创建迭代器的方法iterator

  1. /** 
  2.      * Returns an iterator over the elements in this collection.  There are no 
  3.      * guarantees concerning the order in which the elements are returned 
  4.      * (unless this collection is an instance of some class that provides a 
  5.      * guarantee). 
  6.      * 
  7.      * @return an <tt>Iterator</tt> over the elements in this collection 
  8.      */  
  9.     Iterator<E> iterator();  
/**
     * Returns an iterator over the elements in this collection.  There are no
     * guarantees concerning the order in which the elements are returned
     * (unless this collection is an instance of some class that provides a
     * guarantee).
     *
     * @return an <tt>Iterator</tt> over the elements in this collection
     */
    Iterator<E> iterator();
而迭代器接口中则定义了迭代遍历集合的方法

[javascript] view plain copy
print ?
  1. public interface Iterator<E> {  
  2.     /** 
  3.      * Returns {@code true} if the iteration has more elements. 
  4.      * (In other words, returns {@code true} if {@link #next} would 
  5.      * return an element rather than throwing an exception.) 
  6.      * 
  7.      * @return {@code true} if the iteration has more elements 
  8.      */  
  9.     boolean hasNext();  
  10.   
  11.     /** 
  12.      * Returns the next element in the iteration. 
  13.      * 
  14.      * @return the next element in the iteration 
  15.      * @throws NoSuchElementException if the iteration has no more elements 
  16.      */  
  17.     E next();  
  18. }  
public interface Iterator<E> {
    /**
     * Returns {@code true} if the iteration has more elements.
     * (In other words, returns {@code true} if {@link #next} would
     * return an element rather than throwing an exception.)
     *
     * @return {@code true} if the iteration has more elements
     */
    boolean hasNext();

    /**
     * Returns the next element in the iteration.
     *
     * @return the next element in the iteration
     * @throws NoSuchElementException if the iteration has no more elements
     */
    E next();
}


在调用的过程中:

[javascript] view plain copy
print ?
  1. <span style="white-space:pre">      </span>List<String> list = new ArrayList<String>();  
  2.         list.add("a");  
  3.         list.add("b");  
  4.         for (Iterator<String> iterator = list.iterator(); iterator.hasNext(); ) {  
  5.             System.out.println(iterator.next());  
  6.         }  
		List<String> list = new ArrayList<String>();
		list.add("a");
		list.add("b");
		for (Iterator<String> iterator = list.iterator(); iterator.hasNext(); ) {
			System.out.println(iterator.next());
		}

我们很容易发现,无论我使用的是List还是Set,无论我用的是ArrayList还是Vector,我都可以统一地使用iterator方法生成对应的迭代器进行遍历,当然在jdk1.4还不知道1.5之后,对于这样的遍历我们可以简单使用for(String s : list)的形式,但是从迭代器的例子中我们也很容易意识到工厂方法模式的一个实质作用,当我们已经获取到工厂类的对象的时候可以统一生产对应的实例。当工厂类和实例类的类族非常复杂的时候,统一的创建接口会大大减少开发成本,且不易出错。


前两天一位同学提到了JavaScript中的抽象工厂模式:

[javascript] view plain copy
print ?
  1. /** 
  2.     *抽象工厂 
  3.     * @param subType 传入的是一个对象 
  4.     * @param superType 传入一个字符串 
  5.     * @constructor subType 
  6.     */  
  7.    var VehicleFactory = function(subType,superType){  
  8.        console.log(VehicleFactory.Car);  
  9.        if(typeof VehicleFactory[superType] === "function"){  
  10.            function F(){};  
  11.            F.prototype = new VehicleFactory[superType]();  
  12.            subType.constructor = subType;  
  13.            subType.prototype = new F();  
  14.        } else{  
  15.            throw new Error("没有创建抽象类");  
  16.        }  
  17.    }  
  18.   
  19.    /*一个抽象类*/  
  20.    VehicleFactory.Car = function(){  
  21.        /*构造函数 存放属性*/  
  22.        this.type = "car";  
  23.    }  
  24.    VehicleFactory.Car.prototype = {  
  25.        getType:function(){  
  26.            throw new Error("不可调用getPrice()");  
  27.        }  
  28.    }  
  29.   
  30.    /*实现抽象类*/  
  31.    /*宝马车子类*/  
  32.    var BMW = function(type){  
  33.        this.type = type;  
  34.    }  
  35.   
  36.    VehicleFactory(BMW,'Car');  
  37. *  
  38.    BMW.prototype.getType = function () {  
  39.        return this.type;  
  40.    }  
  41. /  
  42.    var a = new BMW("yay");  
  43.    console.log(a.getType());  
 /**
     *抽象工厂
     * @param subType 传入的是一个对象
     * @param superType 传入一个字符串
     * @constructor subType
     */
    var VehicleFactory = function(subType,superType){
        console.log(VehicleFactory.Car);
        if(typeof VehicleFactory[superType] === "function"){
            function F(){};
            F.prototype = new VehicleFactory[superType]();
            subType.constructor = subType;
            subType.prototype = new F();
        } else{
            throw new Error("没有创建抽象类");
        }
    }

    /*一个抽象类*/
    VehicleFactory.Car = function(){
        /*构造函数 存放属性*/
        this.type = "car";
    }
    VehicleFactory.Car.prototype = {
        getType:function(){
            throw new Error("不可调用getPrice()");
        }
    }

    /*实现抽象类*/
    /*宝马车子类*/
    var BMW = function(type){
        this.type = type;
    }

    VehicleFactory(BMW,'Car');
/*
    BMW.prototype.getType = function () {
        return this.type;
    }
*/
    var a = new BMW("yay");
    console.log(a.getType());

刚看到这段代码的时候我略微有点小懵逼,这段代码不难懂,但是我怎么也没法理解这为什么算是工厂模式,在G4总结的设计模式中,工厂模式是一种对象创建型的模式,然而这段代码分明是实现了继承么,怎么就成了工厂模式了。


但是仔细想想,也并非毫无道理,这里我说下我个人片面的见解,还记得之前我写过的博客,一切都是对象吗?js本身就有着这种奇特的特性,因此在JS中区分创建的是对象还是类,是没有特别大的意义的,这里我们可以把“构造函数”这个事物当做一个类,而具体的构造函数则是一个对象,事实上JS中构造函数本身就是个对象,那这个工厂模式就实现了初始化一个“构造函数”的时候,给定一些初始值。而这种工厂构造最终实现了在JS中继承的作用。


我一直做这样的比喻:如果写代码是打仗,设计模式就是兵书。熟读理解兵书兵法可以用助于自己排兵布阵,但是过分执着于书本内容而不活学活用就容易落得和马谡一样的下场。现阶段我对设计模式的理解是比较浅显的,而设计模式的书则是前人在自身开发经验的总结,随着个人能力的提升,去回顾书本内容自然会获得不同的启发。



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本教程为授权出品教程1) 优秀的程序应该是这样的:阅读时,感觉很优雅;新增功能时,感觉很轻松;运行时,感觉很快速,这就需要设计模式支撑2) 设计模式包含了大量的编程思想,讲授和真正掌握并不容易,网上的设计模式课程不少,大多讲解的比较晦涩,没有真实的应用场景和框架源码支撑,学习后,只知其形,不知其神。就会造成这样结果: 知道各种设计模式,但是不知道怎么使用到真实项目。本课程针对上述问题,有针对性的进行了升级 (1) 授课方式采用 图解+框架源码分析的方式,让课程生动有趣好理解 (2) 系统全面的讲解了设计模式,包括 设计模式七大原则、UML类图-类的六大关系、23种设计模式及其分类,比如 单例模式的8种实现方式、工厂模式的3种实现方式、适配器模式的3种实现、代理模式的3种方式、深拷贝等3) 如果你想写出规范、漂亮的程序,就花时间来学习下设计模式吧课程内容和目标本课程是使用Java来讲解设计模式,考虑到设计模式比较抽象,授课采用 图解+框架源码分析的方式1) 内容包括:设计模式七大原则(单一职责、接口隔离、依赖倒转、里氏替换、开闭原则、迪米特法则、合成复用)、UML类图(类的依赖、泛化和实现、类的关联、聚合和组合) 23种设计模式包括:创建型模式:单例模式(8种实现)、抽象工厂模式、原型模式、建造者模式、工厂模式。结构型模式:适配器模式(3种实现)、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式(3种实现)。行为型模式:模版方法模式、命令模式、访问者模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式(Interpreter模式)、状态模式、策略模式、职责链模式(责任链模式)。2) 学习目标:通过学习,学员能掌握主流设计模式,规范编程风格,提高优化程序结构和效率的能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值