工厂方法模式及在Android源码中的应用

工厂方法

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

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

工厂方法模式的通用模式代码如下:
1. 抽象工厂方法(核心),具体生产什么由子类去实现:

public abstract class Factory {
    public abstract Product createProduct();
}
  1. 具体工厂类(实现了具体业务逻辑):
public class ConcreteFactory extends Factory{
    @Override
    public Product createProduct() {
        return new ConcreteProductA(); // 返回具体的产品对象
        //return new ConcreteProductB(); // 返回具体的产品对象
    }
}
  1. 抽象产品类,由具体的产品类去实现:
public abstract class Product {
    public abstract void method();
}
  1. 具体产品类(包含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");
    }
}
  1. 测试程序:
@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 <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;
    }
}

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

@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<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 对象而生,构造并返回一个具体的迭代器。

其实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,这是不是一个工厂模式的结构呢,其实设计模式离我们非常近!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值