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

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

作者: 付凯强 | 来源:发表于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. 后续

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

    相关文章

      网友评论

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

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