美文网首页
通过示例和源码阐述工厂方法模式

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

作者: 付凯强 | 来源:发表于2018-12-06 16:55 被阅读0次

0. 序言

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

1. 场景

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

2. 变化

  • 当拥有多个工厂的时候,工厂方法模式就变化为了多工厂方法模式。
  • 当拥有一个工厂的时候,简化掉抽象类,将对应的工厂方法改为静态方法,工厂方法模式就变化为了简单工厂模式,或被称为静态工厂模式,它是工厂方法模式的弱化版本。

3. UML类图

工厂方法模式类图.png

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

4. 通用代码

  • 定义抽象产品类Product:
public abstract class Product {
    public abstract void method();
}
  • 定义具体产品类A
public class ConcreteProductA extends Product {

    @Override
    public void method() {
        System.out.println("具体的产品A");
    }
}
  • 定义具体产品类B
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. 替代单例模式

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

  • 定义一个Singleton类:
public class Singleton {
    private Singleton() {

    }

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

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

  • 定义生成单例的工厂类SingletonFactory:
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接口。

  • Iterable:
public interface Iterable<T> {
  
    Iterator<T> iterator();
    ...
}
  • ArrayList:
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迭代器对象。

  • HashSet:
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. 后续

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

相关文章

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

    0. 序言 工厂方法模式的定义:定义一个用于创建对象的接口,让子类决定实例化哪个类。 1. 场景 任何需要生成复杂...

  • 通过示例和源码阐述建造者模式

    0. 序言 建造者模式的定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。 1. 介...

  • 3,简单工厂模式与工厂方法模式

    工厂模式:一个用于创建对象示例的工厂简单工厂模式:通过一个工厂类,来完成创建所有子类的工作工厂方法模式:首先定义一...

  • 设计模式-三种工厂模式-(附Java源码)

    建议结合示例源码理解 1 简单工厂模式 简单工厂模式(Simple Factory Pattern):定义一个工...

  • 工厂模式

    心得:说白了工厂模式就是集中管理其它类示例的场所,根据是否满足开闭原则分为简单工厂模式和(工厂方法模式,抽象工厂模...

  • 工厂方法模式

    一、工厂方法模式概述 工厂方法模式,又称工厂模式、多态工厂模式和虚拟构造器模式,通过定义工厂父类负责定义创建对象的...

  • 浅谈GoF23设计模式-“FactoryMethod”模式

    “FactoryMethod”模式简介:工厂方法模式,又称工厂模式、多态工厂模式和虚拟构造器模式,通过定义工厂父类...

  • 简单工厂模式 工厂方法模式 抽象工厂模式对比

    简单工厂模式: 工厂方法模式: 抽象工厂模式: 缺点:简单工厂模式,若要增加工厂能够生产的产品,必须更改源码;工厂...

  • Spring中都用到了哪些设计模式

    工厂设计模式(简单工厂和工厂方法) Spring使用工厂模式可以通过BeanFactory或Application...

  • 工厂模式

    这次主要介绍的是三种与工厂有关的模式:简单工厂模式、工厂方法模式、抽象工厂模式。课件与源码点击这里。不用工厂模式 ...

网友评论

      本文标题:通过示例和源码阐述工厂方法模式

      本文链接:https://www.haomeiwen.com/subject/ripncqtx.html