Java 设计模式情景分析——工厂方法模式

来源:互联网 发布:js 拼接字符串 编辑:程序博客网 时间:2024/05/17 03:59

转载请注明出处:http://blog.csdn.net/smartbetter/article/details/69226236

工厂方法模式(Factory Pattern),是创建型设计模式之一。其在我们平时开发中应用很广泛,如 Android 中的 Activity 里的各个生命周期方法,以 onCreate 为例,它就可以看作是一个工厂方法,我们在其中可以构造我们的 View 并通过 setContentView 返回 framework 处理等。

定义:定义一个用于创建对象的接口,让子类决定实例化哪个类。

1.工厂方法模式的使用情景

在任何需要生成复杂对象的地方,都可以使用工厂方法模式,复杂对象适合使用工厂方法模式,用 new 就可以完成创建的对象无需使用工厂方法模式。

2.程序中使用工厂方法模式的优缺点

- 工厂方法模式 优点 降低了对象之间的耦合度,工厂模式依赖于抽象的架构,其将实例化的任务交由子类去完成,有非常好的扩展性。 缺点 每次为工厂方法添加新的产品时就要编写一个新的产品类,同还要引入抽象层,必然会导致代码类结构的复杂化。

3.工厂方法模式的UML类图

工厂方法模式的UML类图

4.工厂方法模式的实现

对比UML类图,我们可以写出工厂方法模式的通用模式代码如下:

1.抽象工厂方法(核心),具体生产什么由子类去实现:

public abstract class Factory {    public abstract Product createProduct();}

2.具体工厂类(实现了具体业务逻辑):

public class ConcreteFactory extends Factory{    @Override    public Product createProduct() {        return new ConcreteProductA(); // 返回具体的产品对象    }}

3.抽象产品类,由具体的产品类去实现:

public abstract class Product {    public abstract void method();}

4.具体产品类(包含ConcreteProductA、ConcreteProductB等):

public class ConcreteProductA extends Product {    @Override    public void method() {        System.out.println("ConcreteProductA method");    }}

测试程序:

@Testpublic void factoryTest() throws Exception {    Factory factory = new ConcreteFactory();    Product product = factory.createProduct();    product.method();}

输出:ConcreteProductA method

这种方式比较常见,需要哪个就生产哪个,有时候还可以利用反射的方式更加简洁地来生产具体产品对象,此时,需要在工厂方法的参数列表中传入一个 Class 类来决定是哪一个产品类:

public abstract class Factory {    /**     * @param clz 产品对象类类型     * @param <T> 具体的产品对象     * @return     */    public abstract <T extends Product> T createProduct(Class<T> clz);}

对应的具体工厂类则通过反射获取类的实例即可:

public class ConcreteFactory extends Factory{    @Override    public <T extends Product> T createProduct(Class<T> clz) {        Product p = null;        try {            p = (Product) Class.forName(clz.getName()).newInstance();        } catch (Exception e) {            e.printStackTrace();        }        return (T) p;    }}

再看一下测试代码的实现:

@Testpublic void factoryTest() throws Exception {    Factory factory = new ConcreteFactory();    Product product = factory.createProduct(ConcreteProductA.class);    product.method();}

输出:ConcreteProductA method

需要哪个类的对象传入哪一个类即可,这种方法比较简洁、动态。如果不喜欢这一种,也可以尝试为每一个产品都定义一个具体的工厂,各司其职,像拥有多个工厂的方式我们称为多工厂方法模式,同样当我们的工厂类只有一个的时候,我们还可以简化掉抽象类,只需要将对应的工厂方法给为静态方法即可:

public class Factory {    public static Product createProduct() {        return new ConcreteProductA();    }}

像这样的方式又称为简单工厂模式或者静态工程模式,它是工厂模式的一个弱化版本。

5.Android系统源代码中的应用情景

工厂方法模式应用很广泛,开发中使用到的数据结构中就隐藏着对工厂方法模式的应用,例如 List、Set,List、Set 继承自 Collection 接口,而 Collection 接口继承于 Iterable 接口:

public interface Iterable<T> {    Iterator<T> iterator();}

这意味着 List、Set 接口也会继承 iterator() 方法,下面以 ArrayList 为例进行分析:

ArrayList 中 iterator() 方法的实现就是构造并返回一个迭代器对象:

public class ArrayList<E> extends AbstractList<E>        implements List<E>, RandomAccess, Cloneable, java.io.Serializable {    public Iterator<E> iterator() {        return new Itr();    }    // 迭代器    private class Itr implements Iterator<E> {        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 对象而生,构造并返回一个具体的迭代器。

3 0