设计模式之工厂方法模式与抽象工厂模式

本文介绍了工厂模式,包括简单工厂、工厂方法和抽象工厂三种类型。详细分析了每种模式的应用场景、优缺点及其代码实现,帮助读者理解如何选择合适的工厂模式。
前提

工厂模式,无论是简单工厂、抽象工厂、工厂方法,都是在要创建的对象比较固定,且比较复杂,且客户端无需关注对象创建细节的情况下,才比较适合用。

比如数据库连接,只要只要连接所需信息,创建连接对象的场景比较固定且比较复杂,并且客户端(我们的应用代码)可以不用知道创建细节,只需给一些连接所需信息,这种情况下,工厂模式就十分适合,给工厂配备了连接的所需信息,然后由工厂负责创建连接,客户端无需直到怎么创建,只需知道用工厂get,就能获取到连接来使用。可以避免重复代码。

数据库连接池就是工厂模式很好的体现。

工厂方法模式

由于简单工厂模式的不足,工厂方法可以比较有效弥补。

工厂方法模式是指定义一个创建对象的接口,但是让实现这个接口的类来决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行。工厂方法模式中用户只需要关心什么样的工厂实现会创建出什么样的对象,无需关心创建细节。

工厂方法模式主要解决产品扩展的问题,在简单工厂中,随着产品链的丰富,如果每个课程的创建逻辑有区别的话,工厂的职责会变得越来越多,有点像万能工厂,并不便于维护。违反单一原则和开闭原则。

例子:
还是以pizza为例子,有ChinesePizza、USAPazza。

//pizza接口及两个实现
public interface Pizza {

    void printDesc();
}

public class USAPizza implements Pizza {
    @Override
    public void printDesc() {
        System.out.println("美国Pizza");
    }
}

public class ChinesePizza implements Pizza {
    @Override
    public void printDesc() {
        System.out.println("中国Pizza");
    }
}
//pizza工厂及两个实现类
public interface PizzaFactory {

    Pizza createPizza();
}


public class ChinesePizzaFactory implements PizzaFactory {
    @Override
    public Pizza createPizza() {
        return new ChinesePizza();
    }
}

public class USAPizzaFactory implements PizzaFactory {
    @Override
    public Pizza createPizza() {
        return new USAPizza();
    }
}
//测试
public class TestFactoryMethod {

    public static void main(String[] args) {
        PizzaFactory chinesePizzaFactory = new ChinesePizzaFactory();

        PizzaFactory USAPizzaFactory = new USAPizzaFactory();

        chinesePizzaFactory.createPizza().printDesc();

        USAPizzaFactory.createPizza().printDesc();
    }
}

可以看到 chinesePizzaFactory 生产chinesePizza,USAPizzaFactory 生产USAPizza,如果要新增一个产品,比如UKPizza,那么只需创建一个UKPizza实现Pizza接口,UKPizzaFactory实现PizzaFactory接口,而不用修改工厂类,符合开闭原则和单一职责,适合产品比较多且更新比较频繁的场景。

工厂方法适用于以下场景:
1、创建对象需要大量重复的代码。
2、客户端(应用层)不依赖于产品类实例如何被创建、实现等细节。
3、一个类通过其子类来指定创建哪个对象。
工厂方法也有缺点:
1、类的个数容易过多,增加复杂度。
2、增加了系统的抽象性和理解难度。

抽象工厂

抽象工厂模式(Abastract Factory Pattern)是指提供一个创建一系列相关或相互依赖对象的接口,无须指定他们具体的类。

客户端(应用层)不依赖于产品类实例如何被建、实现等细节,强调的是一系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量重复的代码。需要提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。

产品结构和产品族说明:
举个例子:
java课程的 java视频、java笔记、java课堂源码属性同一产品族。
java课程和python课程属性产品结构。

三个产品族接口及其实现:

public interface Video {

    void videoContent();
}

public class JavaVideo implements Video {
    @Override
    public void videoContent() {
        System.out.println("java课程视频");
    }
}

public class PythonVideo implements Video {
    @Override
    public void videoContent() {
        System.out.println("python课程视频");
    }
}

public interface Source {
    void sourceContent();
}

public class JavaSource implements Source {
    @Override
    public void sourceContent() {
        System.out.println("java课程源码");
    }
}

public class PythonSource implements Source {
    @Override
    public void sourceContent() {
        System.out.println("python课程源码");
    }
}


public interface Note {

    void noteContent();
}

public class JavaNote implements Note {
    @Override
    public void noteContent() {
        System.out.println("java课程笔记");
    }
}

public class PythonNote implements Note {
    @Override
    public void noteContent() {
        System.out.println("python课程笔记");
    }
}
//抽象工厂接口及其实现:
public interface CourseFactory {

//创建一系列产品族
    Note createNote();

    Source createSource();

    Video createVideo();
}

public class JavaCourseFactory implements CourseFactory{

	//创建java课程产品族,java笔记、源码、视频
    @Override
    public Note createNote() {
        return new JavaNote();
    }

    @Override
    public Source createSource() {
        return new JavaSource();
    }

    @Override
    public Video createVideo() {
        return new JavaVideo();
    }
}


public class PythonCourseFactory implements CourseFactory {
    @Override
    public Note createNote() {
        return new PythonNote();
    }

    @Override
    public Source createSource() {
        return new PythonSource();
    }

    @Override
    public Video createVideo() {
        return new PythonVideo();
    }
}

//测试
public class TestAbstractFactory {
    public static void main(String[] args) {
        CourseFactory courseFactory = new JavaCourseFactory();

        courseFactory.createNote().noteContent();
        courseFactory.createSource().sourceContent();
        courseFactory.createVideo().videoContent();
    }
}

在这里插入图片描述

适用场景:

  1. 适用于产品族较多并且不经常变化的情况,比如如果课程有十几二十个产品族,如果使用工厂方法的话,会需要大量工厂类,如果使用抽象工厂,就只需一个产品等级一个工厂类。

缺点:如果新增一个产品族,需要修改所有工厂类及借款的代码,比如新增一个课程评价,那么CourseFactory接口需要新增一个createScore方法,并且其所有子类都要实现修改,很明显违背了开闭原则,所以,如果产品族不稳定的情况下,使用该模式会有一点问题。

工厂方法和抽象工厂的区别

工厂方法是针对产品等级设计的,没有产品族的概念,比如上面的,有 video、source、note三个产品,而没有产品族,维度不一样。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值