Java设计模式之——工厂方法

导语

前一篇文章,简单的讲述了关于简单工厂模式,本篇将继续 讲述工厂方法的定义,以及它的相关实现。且看看在JDK源码或框架源码中,有哪些地方有使用。

 

一、工厂方法的定义和类型

定义:定义一个对象的接口,但让实现这个接口的类来决定实例化哪个类,工厂方法让类的实例化推迟到子类中进行

类型:创建类型

 

二、工厂方法的适用场景和优缺点

适用场景:

  • 创建对象需要重复大量代码
  • 客户端(应用层)不依赖于产品类实例如何被创建、实现等细节
  • 一个类通过其子类来指定创建哪个对象

优点:

  • 用户只需要关心所需产品对应的工厂,无须关心创建细节
  • 加入新产品符合开闭原则,提高可扩展性

缺点:

  • 类的个数容易过多,增加复杂度
  • 增加了系统的抽象性和理解难度

三、工厂方法UML类图和具体代码实现

从上面的UML图中,可以比较清晰的看出每个类之间的关系,工厂方法和简单工厂方法的区别,在于工厂方法中将一个对象的创建交由其子类来实现。但是还是使用代码体现出来比较好。接下来进行代码的展示:

1.首先创建冰箱的抽象类

public abstract class Fridge {
    public abstract void produce();
}

2.再定义冰箱的具体品类实现类

public class PanasonicFridge extends Fridge {
    @Override
    public void produce() {
        System.out.println("-----生产松下冰箱-----");
    }
}
public class GeLiFridge extends Fridge {
    @Override
    public void produce() {
        System.out.println("-----生产格力空调-----");
    }
}

3.创建冰箱的工厂类

这个类和简单工厂方法的区别在于,这个类中的方法是抽象的,且不再传入任何参数。因为这里的具体实现是交由子类工厂去实现的。这里还需要理解一个概念,相同类型的产品,称之为产品等级。这里的产品等级都是在冰箱这个等级上,格力冰箱和松下冰箱都属于同一个产品等级。产品等级和产品族是对比工厂方法和抽象方法的一个重要的概念。

public abstract class FridgeFactory {

    public abstract Fridge getFridge();
}

4.创建子类工厂实现

public class GeLiFridgeFactory extends FridgeFactory {
    @Override
    public Fridge getFridge() {
        return new GeLiFridge();
    }
}
public class PanasonicFridgeFactory extends FridgeFactory {
    @Override
    public Fridge getFridge() {
        return new PanasonicFridge();
    }
}

5.测试类

public class MainTest {
    public static void main(String[] args) {

        FridgeFactory fridgeFactory =new GeLiFridgeFactory();
        Fridge fridge = fridgeFactory.getFridge();
        fridge.produce();

    }
}

测试结果:

四、简单工厂方法在JDK源码中的体现

相信在日常开发中,大多数人都接触过Collection这个接口类,在这类中有这样一个方法:

Iterator<E> iterator();

在这里这个Collection可以视为一个具体的抽象工厂,而 iterator()便是工厂方法。工厂方法也可以指作为工厂的一个方法,iterator()这个方法就正是作为工厂的一个方法。iterator()是以个接口,它有很多是实现类:

从上图中可以看到有很多的实现类,其中一个很熟悉的 ArrayList,点进去看会看到具体实现如下:

    public Iterator<E> iterator() {
        return new Itr();
    }


    private class Itr implements Iterator<E> {
        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;

        Itr() {}

        public boolean hasNext() {
            return cursor != size;
        }

        @SuppressWarnings("unchecked")
        public E next() {
            checkForComodification();
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = 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();
            checkForComodification();

            try {
                ArrayList.this.remove(lastRet);
                cursor = lastRet;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

        @Override
        @SuppressWarnings("unchecked")
        public void forEachRemaining(Consumer<? super E> consumer) {
            Objects.requireNonNull(consumer);
            final int size = ArrayList.this.size;
            int i = cursor;
            if (i >= size) {
                return;
            }
            final Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length) {
                throw new ConcurrentModificationException();
            }
            while (i != size && modCount == expectedModCount) {
                consumer.accept((E) elementData[i++]);
            }
            // update once at end of iteration to reduce heap write traffic
            cursor = i;
            lastRet = i - 1;
            checkForComodification();
        }

        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }

在这里上面的iterator()方法的具体实现就交由子类去实现了,不同子类中实现能得到不同产品的实例。在这里可以理解ArrayList就是一个具体的实现工厂。这里具体的抽象产品就是 Itr 所实现的 Iterator这么一个接口。而 Itr 就是具体的产品。

版权声明:尊重博主原创文章,转载请注明出处:https://blog.csdn.net/zfy163520

发布了41 篇原创文章 · 获赞 8 · 访问量 4273

猜你喜欢

转载自blog.csdn.net/zfy163520/article/details/90642024