Java设计模式之工厂模式

目录

1、简单工厂

实现简单工厂

简单工厂在jdk中的使用

2、工厂方法

产品族和产品等级

实现一个工厂方法

3、抽象工厂

适用场景

优点

缺点

产品等级结构与产品族

实现一个抽象工厂

抽象工厂Java中的使用


1、简单工厂

需要某个产品时 通过工厂来获取对应的产品而不是在需要时直接new对象,将new对象的过程交给简单工厂。

例如:要创建一个学习视频的对象;学习视频包括Java视频,python视频等 如果直接通过new的方式获取对象,获取对象时都需要通过new方式来获取对象

 这样的话调用方与提供方直接耦合,不利于维护。

这时就可以通过简单工厂来帮助调用方来获取对象,起到了调用方与提供方解耦的效果

实现简单工厂

简单工厂实现类

通过简单工厂来获取实例

 查看他们的UML(类图)

 通过类图可以清晰的看出所用产品的创建过程都由VidoeFactory来创建,使用产品时只需实现VidoeFactory,告诉工厂需要什么产品 由他来帮助获取即可

缺点:但是这样做有一个明显的问题 就是当有新的产品类时(如现在多了一个c语言视频)就需要修改VidoeFactory 在createVideo方法中添加一层C类型的判断

 这违反了程序设计中的开闭原则(对扩展开放对修改关闭)

可以通过反射的方式从一定程度上满足开闭原则

修改VidoeFactory

public Video createVideo(Class videoClass){
        Video video = null;
        try {
//            video = (Video) videoClass.newInstance();
            video = (Video) Class.forName(videoClass.getName()).newInstance();

        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        return video;
    }

通过反射可以做到不用修改工厂方法就能创建新的产品

简单工厂在jdk中的使用

Java Calendar(日历类)

Calendar的createCalendar方法通过判断调用者传入的Locale的getUnicodeLocaleType方法返回来生产具体的Calendar

2、工厂方法

产品族和产品等级

在实现工厂方法前要先理解产品族产品等级

例如 网课中由视频和课后作业组成

Java视频和Java课后作业属于同一产品族(同属于Java的产品)

Java视频和python视频属于同一产品等级(都是视频

再例如 美的生产冰箱空调洗衣机等,而海尔也生产冰箱空调洗衣机等

美的生产冰箱空调洗衣机属于同一产品族(同属于美的的产品);海尔生产冰箱空调洗衣机属于同一产品族(同属于海尔的产品)

美的生产冰箱;海尔生产冰箱属于同一产品等级(都是冰箱);美的生产空调;海尔生产空调属于同一产品等级(都是空调

工厂方法是解决产品等级的   抽象工厂就是用来解决产品族的 这是工厂方法和抽象工厂最大的区别以及灵活运用的点

工厂方法的父工厂类,只定义产品的生产方式 不做具体的实现方式  具体实现由各产品工厂类负责

实现一个工厂方法

父工厂类

子工厂

JavaVideoFactory负责生产JavaVideo

public class JavaVideoFactory extends VideoFactory {

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

PythonVideoFactory负责生产PythonVideo

public class PythonVideoFactory extends VideoFactory {

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

客户端需要某个产品时直接通过该产品对应的具体工厂就可获取

例如要获取JavaVideo

public class Test {

    public static void main(String[] args) {
        // 想要获取JavaVideo产品只需创建一个JavaVideoFactory对象
        VideoFactory videoFactory = new JavaVideoFactory();
        // 由JavaVideoFactory来生产JavaVideo 不需要关注video的生产细节
        Video video = videoFactory.createVideo();
        String product = video.product();
        System.out.println("product: "+product);
    }
}

现在想要扩展一个能生产c语言的视频,只需要创建一个CVideoFactory实现VideoFactory的工厂方法即可,不需要像普通工厂那样修改工厂代码,可扩展性更强

public class CVideoFactory  extends VideoFactory {

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

查看UML(类图)

 可以看出父类工厂只负责产品的创建规范,而具体的创建方式由各子类工厂负责,有扩展的需求时只需要扩展对应的video和factory即可,不需要做修改

3、抽象工厂

定义:抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口

无需指定它们具体的类

类型:创建型

适用场景

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

优点

  • 具体产品在应用层代码隔离,无需关心创建细节
  • 将一个系列的产品族统一到一起创建

缺点

  • 规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口
  • 增加了系统的抽象性和理解难度

产品等级结构与产品族

图中y轴(颜色相同)为产品族,x轴(形状相同)为产品等级

例如 美的生产冰箱空调洗衣机等,而海尔也生产冰箱空调洗衣机等

美的生产冰箱空调洗衣机属于同一产品族(同属于美的的产品);海尔生产冰箱空调洗衣机属于同一产品族(同属于海尔的产品)

美的生产冰箱;海尔生产冰箱属于同一产品等级(都是冰箱);美的生产空调;海尔生产空调属于同一产品等级(都是空调

抽象工厂就是用来解决产品族问题的

实现一个抽象工厂

抽象工厂父类提供规则

public interface CourseFactory {
    Article getArticle();
    Video getVideo();
}

具体子类工厂

Java产品族工厂,能生产Java的所有产品

public class JavaCourseFactory implements CourseFactory {
    @Override
    public Article getArticle() {
        return new JavaArticle();
    }

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

Python产品族工厂,能生产Python的所有产品

public class PythonCourseFactory implements CourseFactory {
    @Override
    public Article getArticle() {
        return new PythonArticle();
    }

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

客户端获取Java产品

public class Test {
    public static void main(String[] args) {
        CourseFactory courseFactory = new JavaCourseFactory();
        Article article = courseFactory.getArticle();
        Video video = courseFactory.getVideo();
        System.out.println("article: "+article.produce());
        System.out.println("video: "+video.product());
    }
}

查看UML(类图)

 可以看出如果想要扩展新的产品族 例如 现在多了一个C语言的产品只需要添加C语言的视频和笔记类以及新增C语言的产品工厂即可,对新增产品族是非常便于扩展的

但是如果要在产品族中增加新的产品等级,例如 现在课程除了需要视频和笔记外又多了一个课堂源码模块,这时就需要对所有的工厂进行修改,违背了开闭原则

抽象工厂Java中的使用

mybatis的核心SqlSessionFactory就是使用了抽象工厂

父类工厂

 子类工厂

 SqlSessionFactory能生产一个产品族的所种产品,通过不同的子类工厂,客户端不需注意生产的任何细节就能获取想要的产品。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值