工厂方法模式及在Android源码中的应用
工厂方法
在任何需要生成复杂对象的地方,都可以使用工厂方法模式,复杂对象适合使用工厂方法模式,用 new 就可以完成创建的对象无需使用工厂方法模式。
优点:降低了对象之间的耦合度,工厂模式依赖于抽象的架构,其将实例化的任务交由子类去完成,有非常好的扩展性。
缺点:每次为工厂方法添加新的产品时就要编写一个新的产品类,同还要引入抽象层,必然会导致代码类结构的复杂化。
工厂方法模式的通用模式代码如下:
1. 抽象工厂方法(核心),具体生产什么由子类去实现:
public abstract class factory { public abstract product createproduct(); }具体工厂类(实现了具体业务逻辑):
public class concretefactory extends factory{ @override public product createproduct() { return new concreteproducta(); // 返回具体的产品对象 //return new concreteproductb(); // 返回具体的产品对象 } }抽象产品类,由具体的产品类去实现:
public abstract class product { public abstract void method(); }具体产品类(包含concreteproducta、concreteproductb等):
public class concreteproducta extends product { @override public void method() { system.out.println("concreteproducta method"); } } public class concreteproductb extends product { @override public void method() { system.out.println("concreteproductb method"); } }测试程序:
@test public void factorytest() throws exception { factory factory = new concretefactory(); product product = factory.createproduct(); product.method(); }
输出:concreteproducta method
这种方式比较常见,需要哪个就生产哪个,有时候还可以利用反射的方式更加简洁地来生产具体产品对象,此时,需要在工厂方法的参数列表中传入一个 class 类来决定是哪一个产品类:
public abstract class factory { /** * @param clz 产品对象类类型 * @param 具体的产品对象 * @return */ public abstract t createproduct(class clz); }
对应的具体工厂类则通过反射获取类的实例即可:
public class concretefactory extends factory{ @override public t createproduct(class clz) { product p = null; try { p = (product) class.forname(clz.getname()).newinstance(); } catch (exception e) { e.printstacktrace(); } return (t) p; } }
再看一下测试代码的实现:
@test public void factorytest() throws exception { factory factory = new concretefactory(); product product = factory.createproduct(concreteproducta.class); product.method(); product product = factory.createproduct(concreteproducta.class); product.method(); }
输出:
concreteproducta method
concreteproductb method
需要哪个类的对象传入哪一个类即可,这种方法比较简洁、动态。如果不喜欢这一种,也可以尝试为每一个产品都定义一个具体的工厂,各司其职,像拥有多个工厂的方式我们称为多工厂方法模式,同样当我们的工厂类只有一个的时候,我们还可以简化掉抽象类,只需要将对应的工厂方法给为静态方法即可:
public class factory { public static product createproduct() { return new concreteproducta(); } }
源码中的应用">源码中的应用
工厂方法模式应用很广泛,开发中使用到的数据结构中就隐藏着对工厂方法模式的应用,例如 list、set,list、set 继承自 collection 接口,而 collection 接口继承于 iterable 接口:
public interface iterable { iterator iterator(); }
这意味着 list、set 接口也会继承 iterator() 方法,下面以 arraylist 为例进行分析:
arraylist 中 iterator() 方法的实现就是构造并返回一个迭代器对象:
public class arraylist extends abstractlist implements list, randomaccess, cloneable, java.io.serializable { public iterator iterator() { return new itr(); } // 迭代器 private class itr implements iterator { protected int limit = java.util.arraylist.this.size; int cursor; // index of next element to return int lastret = -1; // index of last element returned; -1 if no such int expectedmodcount = modcount; public boolean hasnext() { return cursor < limit; } @suppresswarnings("unchecked") public e next() { if (modcount != expectedmodcount) throw new concurrentmodificationexception(); int i = cursor; if (i >= limit) throw new nosuchelementexception(); object[] elementdata = java.util.arraylist.this.elementdata; if (i >= elementdata.length) throw new concurrentmodificationexception(); cursor = i + 1; return (e) elementdata[lastret = i]; } public void remove() { if (lastret < 0) throw new illegalstateexception(); if (modcount != expectedmodcount) throw new concurrentmodificationexception(); try { java.util.arraylist.this.remove(lastret); cursor = lastret; lastret = -1; expectedmodcount = modcount; limit--; } catch (indexoutofboundsexception ex) { throw new concurrentmodificationexception(); } } // 代码省略 } // 代码省略 }
其中的 iterator() 方法其实就相当于一个工厂方法,专为 new 对象而生,构造并返回一个具体的迭代器。
其实android中对工厂方法模式的应用更多,先看如下代码:
public class aactivity extends activity{ @override protected void oncreate(bundle savedinstancestate){ super.oncreate(savedinstancestate); setcontentview(new linearlayout(this)); } }
实际上,oncreate方法就相当于一个工厂方法,因为linearlayout是一个viewgroup,而viewgroup又继承于view,简单地说,所有控件都是view的子类。在aactivity的oncreate方法中构造一个view对象,并设置为当前的contentview返回给framework处理,如果现在又有一个bactivity,这时又在oncreate方法中通过setcontentview方法设置另外不同的view,这是不是一个工厂模式的结构呢,其实设计模式离我们非常近!!!