前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >工厂方法模式及在Android源码中的应用

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

作者头像
见得乐
发布2022-09-08 15:49:32
发布2022-09-08 15:49:32
49900
代码可运行
举报
文章被收录于专栏:LearnPathLearnPath
运行总次数:0
代码可运行

工厂方法

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

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

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

代码语言:javascript
代码运行次数:0
复制
public abstract class Factory {
    public abstract Product createProduct();
}
  1. 具体工厂类(实现了具体业务逻辑):
代码语言:javascript
代码运行次数:0
复制
public class ConcreteFactory extends Factory{
    @Override
    public Product createProduct() {
        return new ConcreteProductA(); // 返回具体的产品对象
        //return new ConcreteProductB(); // 返回具体的产品对象
    }
}
  1. 抽象产品类,由具体的产品类去实现:
代码语言:javascript
代码运行次数:0
复制
public abstract class Product {
    public abstract void method();
}
  1. 具体产品类(包含ConcreteProductA、ConcreteProductB等):
代码语言:javascript
代码运行次数:0
复制
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. 测试程序:
代码语言:javascript
代码运行次数:0
复制
@Test
public void factoryTest() throws Exception {
    Factory factory = new ConcreteFactory();
    Product product = factory.createProduct();
    product.method();
}

输出:ConcreteProductA method

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

代码语言:javascript
代码运行次数:0
复制
public abstract class Factory {
    /**
     * @param clz 产品对象类类型
     * @param <T> 具体的产品对象
     * @return
     */
    public abstract <T extends Product> T createProduct(Class<T> clz);
}

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

代码语言:javascript
代码运行次数:0
复制
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;
    }
}

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

代码语言:javascript
代码运行次数:0
复制
@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

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

代码语言:javascript
代码运行次数:0
复制
public class Factory {
    public static Product createProduct() {
        return new ConcreteProductA();
    }
}

源码中的应用

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

代码语言:javascript
代码运行次数:0
复制
public interface Iterable<T> {
    Iterator<T> iterator();
}

这意味着 List、Set 接口也会继承 iterator() 方法,下面以 ArrayList 为例进行分析: ArrayList 中 iterator() 方法的实现就是构造并返回一个迭代器对象:

代码语言:javascript
代码运行次数:0
复制
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中对工厂方法模式的应用更多,先看如下代码:

代码语言:javascript
代码运行次数:0
复制
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,这是不是一个工厂模式的结构呢,其实设计模式离我们非常近!!!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-11-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 工厂方法
  • 源码中的应用
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档