简单工厂模式:
简单工厂模式可以认为是一个创建实例的过程,可以代替new的方式,创建一个新的实例。创建实例new的时候要多考虑一下,看是否可以使用工厂模式,虽然可能多做一些工作,但是系统可能会有更少程度的修改。
直白的说就是把对象创建的过程封装到一个新的类中去,比如这个类创建的初始化过程比较麻烦,按老方法就是把这些全放在这个类的构造函数中,但是这样显然不利于维护,所以就把这部分内容提取出来放到一个新的类中,这个类的某个create方法可以返回一个所需要的对象的实例。
简单工厂模式的实质就是工厂类根据传入的参数来动态的决定到底要创建哪一个实例出来,最后把这个实例返回就OK了。
最明显的就是容器中的使用Iterator进行遍历,
Iterator it = list.iterator();
while(it.hasNext()){
//using “it.next();”do some businesss logic
}
通过list.iterator()的时候,就使用了工厂模式,这里会在内部自动地返回每次list中的Object的具体的类型,我们并不用关心,list中元素的内容究竟是那个类,这个在工厂类中就考虑到了。
工厂模式的适用范围
• 在编码时不能预见需要创建哪一种类的实例。
• 一个类使用它的子类来创建对象。
• 开发人员不希望创建了哪个类的实例以及如何创建实例的信息暴露给外部程序。
http://wxg6203.iteye.com/blog/740229
具体的实现中包含几个角色:
抽象产品:产品类的接口
具体产品:这里可以有多种对于抽象产品的实现过程)
工厂类:具体产品的直接调用者,根据不同的情况调用具体产品,生成不同的产品类实例并返回。
客户端:实际上就相当于测试类,调用工厂类产生实例(这里调用的时候根据运行的时候客户端传给工厂类方法的参数来生成不同的实例),并且调用实例的方法,直接用接口作为引用就就行。
借用一下这个里面的例子
(http://www.cnblogs.com/java-my-life/archive/2012/03/28/2418836.html)
模拟一个电脑组装的流程,假设组装一个电脑需要选定CPU,选定主板,其他操作,三个步骤。现在就针对选CPU这个步骤来说,假设有Intel以及AMD两种品牌,通过运行时候传递进来的信息,采用工厂模式就可以返回不同的CPU实例。
//抽象产品: public interface cpu { public void info(); } //两个具体的产品实现抽象接口: public class AMDcpu implements cpu{ public void info() { System.out.println("this is a AMDcpu"); } } public class Intelcpu implements cpu{ public void info() { // TODO Auto-generated method stub System.out.println("this is an Intel cpu"); } } //工厂类: public class simpleFactory { //在实际中 这里的传入的参数可以是各种形式的 只要能起到区别的效果就好了 public cpu createcpu(int i){ cpu c=null; if(i==1) c=new Intelcpu(); if(i==2) c=new AMDcpu(); return c; } } //具体的客户端类: public class Client { public static void main(String[] args) { //生成工厂实例 simpleFactory factory=new simpleFactory(); //如果执行中需要创建一个amd cpu cpu c1=factory.createcpu(1); c1.info(); //如果执行中需要创建一个intel cpu cpu c2=factory.createcpu(2); c2.info(); } }
抽象工厂模式:
抽象工厂模式参考了:
http://www.cnblogs.com/java-my-life/archive/2012/03/28/2418836.html
http://blog.csdn.net/ipqxiang/article/details/1955677
还是上面的那个组装电脑的例子,这里考虑全面的情况,其实就是在原先问题的升级版,在二维的情况中:
根据上面的图,很清楚的可以看出这是一个从二维的角度进行分类问题,我们把横轴的分类称为“等级”,把纵轴的分类称为“产品簇”。当然也可以反过来。
在上面的简单的工厂模式中,只有一个等级(选cpu),仅仅需要一个工厂模式就OK了,在这个问题中有多个等级,那就需要有多个工厂类,之前的简单工程模式是在一维的情况,这个抽象工厂模式是多维的情况。
由于横纵轴反过来没什么关系就是怎么称呼没关系,仅仅是一个分类的角度,我们把纵轴的指标看成等级,在等级为AMD类型的时候,有三种针对AMD类型产品的选择,在等级为Intel的时候,也有三种针对Intel产品的选择。对于每一列,Intel cpu以及AMD cpu就组成了一个产品簇,之后的每一类都组成了其他的产品簇。
每一个等级可以用一个工厂类来描述,在这个基础上再进一步抽象,我们可以有一个抽象工厂abstractFactory,通过继承抽象工厂,这个抽象工厂有createCpu,createBios,otherOption三个主要的步骤,在这个基础上,可以实现一个具体的AMD工厂类,以及一个Intel工厂类。
//基本代码: public interface abstractFactory { public abstractcpu createCpu(); public abstractbios createBios(); public abstractoptions otherOptions(); } //两个具体的工厂类: public class AMDFactory implements abstractFactory{ public abstractcpu createCpu() { // TODO Auto-generated method stub return new AMDcpu(); } public abstractbios createBios() { // TODO Auto-generated method stub return new AMDbios(); } public abstractoptions otherOptions() { // TODO Auto-generated method stub return new AMDoptions(); } } public class IntelFactory implements abstractFactory{ @Override public abstractcpu createCpu() { // TODO Auto-generated method stub return new Intelcpu(); } @Override public abstractbios createBios() { // TODO Auto-generated method stub return new Intelbios(); } @Override public abstractoptions otherOptions() { // TODO Auto-generated method stub return new Inteloptions(); } }
之后三个不同的原材料,就是所谓的三个产品簇,也要分别有各自的抽象类以及具体类:
//Cpu的抽象类和具体类 public interface abstractcpu { public void info(); } class AMDcpu implements abstractcpu{ @Override public void info() { System.out.println("this is an AMDcpu"); } } class Intelcpu implements abstractcpu{ @Override public void info() { System.out.println("this is an Intelcpu"); } } //Bios的抽象类和具体类 public interface abstractbios { public void info(abstractcpu cpu); } class AMDbios implements abstractbios{ @Override public void info(abstractcpu cpu) { System.out.println("this is an AMDbios depents on "+cpu.getClass()); } } class Intelbios implements abstractbios{ @Override public void info(abstractcpu cpu) { System.out.println("this is an Intelbios depends on "+cpu.getClass()); } } //Other Options的抽象类和具体类: public interface abstractoptions { public void info(); } class AMDoptions implements abstractoptions{ @Override public void info() { System.out.println("this is an AMDoptions"); } } class Inteloptions implements abstractoptions{ @Override public void info() { System.out.println("this is an Inteloptions"); } }
之后就可以生成具体的makeupProcess类了,就表示组装的流程,里面包括准备原材料以及生成具体的实例两个方法,这两个方法都是针对接口来进行实现的,这就是抽象的目的,通过抽象实现了某种程度上的降维,使得维护更加方便。
public class makeupProcess { //所需要的原材料 abstractcpu cpu=null; abstractbios bios=null; abstractoptions oteroptions=null; //进行准备 传入一个抽象工厂类 public void prerare(abstractFactory factory){ this.cpu=factory.createCpu(); this.bios=factory.createBios(); this.oteroptions=factory.otherOptions(); } //具体组装 public void makeup(abstractFactory factory){ prerare(factory); this.cpu.info(); this.bios.info(); this.oteroptions.info(); System.out.println("do the make up process"); System.out.println("return an computer instance using the "+factory.getClass()); }
最后是测试的类,相当于客户端进行具体调用的过程:
public class Client { public static void main(String[] args) { //创建组装过程类 一般情况这个类要是单例的比较好 makeupProcess process=new makeupProcess(); //根据实际的运行情况 比如此时需要组装一个AMD的电脑 process.makeup(new AMDFactory()); System.out.println("------------------------"); //比如此时又要生成一个Intel电脑 process.makeup(new IntelFactory()); } } 具体的输出结果如下: /* this is an AMDcpu this is an AMDbios depents on class com.designpatten.abstractFactorypatten.AMDcpu this is an AMDoptions do the make up process return an computer instance using the class com.designpatten.abstractFactorypatten.AMDFactory ------------------------ this is an Intelcpu this is an Intelbios depends on class com.designpatten.abstractFactorypatten.Intelcpu this is an Inteloptions do the make up process return an computer instance using the class com.designpatten.abstractFactorypatten.IntelFactory */
感觉关键的地方主要有两个地方:
1、 原材料:即使每个产品簇的抽象类和具体的实现类,以及两个工厂方法的抽象类和具体的实现类。
2、 makeupProcess中针对抽象类的编程,里面的 prepare以及makeup两个方法是针对抽象Factory实现的,所以不管传进去哪个Factory都可以进行对应的操作,这就是抽象的好处,相当于抓住了本质,所谓多态,就是利用抽象来实现的这种以不变应万变的效果,就是抓住了它们相同的本质。
抽象工厂模式是工厂方法模式的升级版本,他用来创建一组相关或者相互依赖的对象(上面的例子里假设bios的info方法依赖与cpu,只需要传入abstractcpu接口就好了)。他与工厂方法模式的区别就在于,简单工厂模式针对的是一个产品等级结构;而抽象工厂模式则是针对的多个产品等级结构。在编程中,通常一个产品结构,表现为一个接口或者抽象类,也就是说,简单工厂模式提供的所有产品都是衍生自同一个接口或抽象类,而抽象工厂模式所提供的产品则是衍生自不同的接口或抽象类(就是说可以仅仅创建一个过程类,这个过程类可以来接受不同的工厂类实例,来生成对应的实例)。