23种设计模式之工厂方法模式

回顾 简单工厂模式 ,它虽然实现了对象创建和使用的分离,但是每新增个产品就要修改工厂类 还是违背了OCP开闭原则 而工厂方法模式可以解决这个问题

工厂方法模式

工厂方法模式(FACTORY METHOD)是一种常用的类创建型设计模式,此模式的核心精神是封装类中变化的部分,提取其中个性化善变的部分为独立类,通过依赖注入以达到解耦、复用和方便后期维护拓展的目的。它的核心结构有以下四个角色

  • 抽象产品:定义了产品的规范,描述了产品的主要特征和功能
  • 具体产品:实现了抽象产品定义的接口,由具体工厂创建
  • 抽象工厂:提供了创建产品的接口
  • 具体工厂:主要实现抽象工厂的抽象方法完成具体产品的创建

【案例】

假设有家咖啡店 它目前只卖美式咖啡和拿铁咖啡,但是随着业务的发展,它又加入了卡布奇诺和摩卡咖啡, 小张、小王、小李想喝不同的咖啡,请设计程序完成咖啡店的点餐功能(还是这个案例)

抽象产品

public abstract class Coffee{
    abstract String getName();
    void addSugar(){ System.out.println("加糖"); }
    void addMilk(){ System.out.println("加奶"); }
}

具体产品

美式咖啡

public class AmericanCoffee extends Coffee {
    String getName(){
    	return "美式咖啡";
    }
}

拿铁咖啡

public class LatteCoffee extends Coffee {
    String getName(){
    	return "拿铁咖啡";
    }
}

抽象工厂

提供了创建产品的接口

public interface CoffeeFactory{
    Coffee createCoffee();
}

具体工厂

美式咖啡工厂

public class AmericanCoffeeFactory implements CoffeeFactory{
    public Coffee createCoffee(){
        return new AmericanCoffee();
    }
}

拿铁咖啡工厂

class LatteCoffeeFactory implements CoffeeFactory{
    public Coffee createCoffee(){
        return new LatteCoffee();
    }
}

点餐

public class CoffeeStore {

    public Coffee orderCoffee(CoffeeFactory factory){
        Coffee coffee = factory.createCoffee();
        coffee.addSugar();
        coffee.addMilk();
        System.out.println(coffee.getName()+"制作中...");
        return  coffee;
    }

    public static void main(String[] args) {
        CoffeeStore store = new CoffeeStore();
        CoffeeFactory factory = new AmericanCoffeeFactory(); //小张想喝美式咖啡
        store.orderCoffee(factory);
        CoffeeFactory factory1 = new LatteCoffeeFactory(); //小王想喝拿铁咖啡
        store.orderCoffee(factory1);
    }
}

现在想要加入马布奇诺或摩卡咖啡就无需修改工厂类,只需要在创建一个具体的产品类和一个具体的产品工厂就可以实现,满足了OCP开闭原则

//新添加的具体产品类
public class Cappuccino extends Coffee{
    String getName(){return "卡布奇诺";}
}
//新添加的具体工厂类
public class CappuccinoFactory implements CoffeeFactory{
    public Coffee createCoffee(){
        return new Cappuccino();
    }
}

这时小李想喝卡布奇诺就可以在主方法中new CappuccinoFactory

 public static void main(String[] args) {
        CoffeeStore store = new CoffeeStore();
        CoffeeFactory factory1 = new LatteCoffeeFactory(); //小王想喝拿铁咖啡
        store.orderCoffee(factory1);
        CoffeeFactory factory2 = new CappuccinoFactory(); //小李想喝卡布奇诺
        store.orderCoffee(factory2);
    }

工厂方法模式的优缺点

  • 优点:
    1、用户只需要知道具体工厂的名称就可以得到你想要的产品,无需知道产品的创建过程
    2、在系统增加新的产品只需要添加具体产品类和对应的具体工厂类,无需对原工厂进行任何修改,满足OCP开闭原则
  • 缺点
    1、每增加一个产品就要增加一个具体的产品类和对应的具体工厂类,这增加了系统的复杂度
    2、抽象产品只能生产一种产品

工厂方法模式在JDK中的应用

在这里插入图片描述

抽象产品类

public interface Iterator<E> {
    boolean hasNext();
    E next();
}

具体产品类

//ListItr 迭代器(LinkList内部类)
 private class ListItr implements ListIterator<E> {
        ListItr(int index) {
            next = (index == size) ? null : node(index);
            nextIndex = index;
        }
        public boolean hasNext() {//重写的代码...}
        public E next() {//重写的代码...}
}
//Itr 迭代器(ArrayList内部类)
 private class Itr implements Iterator<E> {
        Itr() {}
        public boolean hasNext() {//重写的代码...}
        public E next() {//重写的代码...}
}

抽象工厂

public interface Collection<E> extends Iterable<E> {
	//其他代码...
	Iterator<E> iterator();
	//其他代码...
}

具体工厂

public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable{
    //其他代码...
	public Iterator<E> iterator() {
        return new Itr();
    }
    //其他代码...
}
public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable{
    //其他代码...
	public ListIterator<E> listIterator(int index) {
        checkPositionIndex(index);
        return new ListItr(index);
    }
	//其他代码...
}

使用具体产品

public class Test {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        //List<String> list = new LinkedList<>();
        //下面的代码不用改想使用不同的迭代器就new不同的工厂对象即可
        Iterator<String> iterator = list.iterator();
    }
}

另外还有DataFormat类中getInstance()方法使用的是工厂方法模式
Calendar类中的getInstance()方法也是使用的工厂方法模式

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值