通过示例和源码阐述工厂方法模式

2018-12-06  本文已影响0人  付凯强

0. 序言

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

1. 场景

任何需要生成复杂对象或多个对象的地方,都可以使用工厂方法模式。

2. 变化

3. UML类图

工厂方法模式类图.png

角色介绍:
① 抽象工厂Factory:工厂方法模式的核心。
② 具体工厂ConcreteFactory:实现了具体的业务逻辑。
③ 抽象产品Product:工厂方法模式所创建的产品的父类。
④ 具体产品ConcreteProduct:为实现抽象产品的某个具体产品的对象。

4. 通用代码

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

    @Override
    public void method() {
        System.out.println("具体的产品A");
    }
}
public class ConcreteProductB extends Product {

    @Override
    public void method() {
        System.out.println("具体的产品B");
    }
}
public abstract class Factory {
    public abstract Product createProduct();
}
public class ConcreteFactory extends Factory {
    @Override
    public Product createProduct() {
        return new ConcreteProductA();
    }
}
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Factory factory = new ConcreteFactory();
        Product product = factory.createProduct();
        product.method();
    }
}
12-06 14:15:30.911 14725-14725/com.smartisan.factory I/System.out: 具体的产品A

说明:ConcreteFactory用来具体生产对象:这里我们生产的是产品A的对象,如果想得到产品B的对象,我们修改下代码即可:

public class ConcreteFactory extends Factory {
    @Override
    public Product createProduct() {
        return new ConcreteProductB();
    }
}
12-06 14:18:31.260 15059-15059/com.smartisan.factory I/System.out: 具体的产品B

5. 反射的应用

如果按照以上方式,需要哪个对象就生产哪个对象,当然也可以利用反射更简洁地生产具体产品对象,在工厂方法的参数列表中传入一个Class类来决定是哪一个产品类:

public abstract class Factory {
    public abstract <T  extends Product> T createProduct(Class<T> tClass);
}
public class ConcreteFactory extends Factory {

    @Override
    public <T extends Product> T createProduct(Class<T> tClass) {
        Product product = null;
        try {
            product = (Product) Class.forName(tClass.getName()).newInstance();
        } catch (IllegalAccessException | InstantiationException | ClassNotFoundException e) {
            e.printStackTrace();
        }
        return (T) product;
    }
}
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Factory factory = new ConcreteFactory();
        Product product = factory.createProduct(ConcreteProductB.class);
        product.method();
    }
}
12-06 14:28:50.155 15412-15412/com.smartisan.factory I/System.out: 具体的产品B

说明:通过反射,你需要哪一个类的对象就传入哪一个类的类型即可,方法简洁、动态。

6. 多工厂方法模式

我们也可以为每个产品定义一个工厂类,逻辑更清楚,不过类就增多了。

public abstract class Factory {
    public abstract Product createProduct();
}
public class ConcreteFactoryA extends Factory {
    @Override
    public Product createProduct() {
        return new ConcreteProductA();
    }
}
public class ConcreteFactoryB extends Factory {
    @Override
    public Product createProduct() {
        return new ConcreteProductB();
    }
}
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Factory factoryA = new ConcreteFactoryA();
        Product productA = factoryA.createProduct();
        productA.method();

        Factory factoryB = new ConcreteFactoryB();
        Product productB = factoryB.createProduct();
        productB.method();
    }
}

7. 简单工厂模式

当我们只有一个工厂的时候,我们可以简化掉抽象工厂类,只需要将对应的工厂方法改为静态方法:

public  class Factory {
    public static Product createProduct(){
        return new ConcreteProductB();
//        return new ConcreteProductA();
    }
}
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        Product productA = Factory.createProduct();
        productA.method();
    }
}

说明:简单工程模式是工厂方法模式的弱化版本。

8. 延迟初始化

延迟初始化的意思就是一个对象被消费完毕后,并不立刻释放,工厂类保持其初始状态,等待再次被使用,其实就是把对象缓存,这样不用每次调用就new 对象了。

public class ProductFactory {
    public static final int TYPE_PRODUCT_A = 1;
    public static final int TYPE_PRODUCT_B = 2;
    private static final Map<String, Product> map = new HashMap<>();

    public static synchronized Product createProduct(String type) throws Exception {
        Product product = null;
        if (map.containsKey(type)) {
            product = map.get(type);
        } else {
            if (type.equals(TYPE_PRODUCT_A)) {
                product = new ConcreteProductA();
            } else {
                product = new ConcreteProductB();
            }
            map.put(type, product);
        }
        return product;
    }
}

说明:Map容器中如果有缓存的对象,就取出来用,如果没有,就生成一个对象并缓存这个对象到Map集合中。

9. 替代单例模式

开发中会有很多类是单例模式的,为了简化代码,我们可以用一个工厂单例类,对这些类进行统一操作,简化需要设置为单例的类,示例如下:

public class Singleton {
    private Singleton() {

    }

    public  void doSomething(){
        // 业务处理
        System.out.println("哈哈,我是单例模式了");
    }
}

说明:这里我们私有了构造方法。

public class SingletonFactory {

    private static final Map<String, Object> map = new HashMap<>();

    public static synchronized Object createSingleton(Class clazz) throws Exception {
        Object sObject;
        if (map.containsKey(clazz.getName())) {
            sObject = map.get(clazz.getName());
        } else {
            Class aClass = Class.forName(clazz.getName());
            // 获得无参构造
            Constructor constructor = aClass.getDeclaredConstructor();
            // 设置无参构造是可访问的
            constructor.setAccessible(true);
            // 产生一个实例对象
            sObject = constructor.newInstance();
            // 缓存对象
            map.put(clazz.getName(), sObject);
        }
        return sObject;
    }
}
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Singleton singleton_01;
        Singleton singleton_02;
        try {
            singleton_01 = (Singleton) SingletonFactory.createSingleton(Singleton.class);
            Log.i("fukq", "singleton_01的内存地址:" + singleton_01);
            singleton_02 = (Singleton) SingletonFactory.createSingleton(Singleton.class);
            Log.i("fukq", "singleton_02的内存地址:" + singleton_02);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
12-06 16:04:39.928 17196-17196/? I/fukq: singleton_01的内存地址:com.smartisan.factory.Singleton@879a4a1
    singleton_02的内存地址:com.smartisan.factory.Singleton@879a4a1

说明:打印出来的内存地址一样,证明实现了类的单例模式。唯一需要类所做得就是私有自己的构造方法即可。我们想要哪个类实现单例,我们只需要传入它的class名字即可。

10. 源码实现:

以List和Set为例,它俩都继承了Collection接口,而Collection接口继承于Iterable接口。

public interface Iterable<T> {
  
    Iterator<T> 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> {
    ...
        }

说明:会看到ArrayList中的iterator方法返回一个ltr迭代器对象。

public class HashSet<E>
    extends AbstractSet<E>
    implements Set<E>, Cloneable, java.io.Serializable
{
    public Iterator<E> iterator() {
        return map.keySet().iterator();
    }
    ...
}

其中map代码:

    private transient HashMap<E,Object> map;

其中keySet代码:

    public Set<K> keySet() {
        Set<K> ks = keySet;
        if (ks == null) {
            ks = new KeySet();
            keySet = ks;
        }
        return ks;
    }

其中KeySet代码:

 final class KeySet extends AbstractSet<K> {
        public final Iterator<K> iterator()     { return new KeyIterator(); }
        ...
}

说明:会看到HaskSet最终返回的是KeySet中的一个迭代器对象。ArrayList和HashSet中的iterator方法其实就相当于一个工厂方法,转为new对象而生,这里Iterator方法是构造并返回一个具体的迭代器。

11. 后续

如果大家喜欢这篇文章,欢迎点赞!
如果想看更多 设计模式 方面的技术,欢迎关注!

上一篇下一篇

猜你喜欢

热点阅读