【设计模式】创建型-工厂模式

一听“工厂”就知道,肯定是产生产品的地方。不同的工厂可以生产不同的产品,如果没有区分工厂,就实际生活中,印度的小作坊,什么都能做,吃的喝的用的,全出自一个地方。这样对生产的产品来说是非常的混乱,不专业,而且产品种类太多,容易出现原材料缺失等等。。

有了工厂模式,就可以解决这些混乱的问题。咱们就拿CSDN首页左边拦的分类举例子把。“我是CSDN的编辑,现在我需要构造5个分类出来!”

public class BuildCategory {
    public static void main(String[] args) {
        System.out.println("建立类别:首页");
        System.out.println("建立类别:博客");
        System.out.println("建立类别:学习");
        System.out.println("建立类别:下载");
        System.out.println("建立类别:社区");
    }
}

你有什么感想?如果我需要再建立“视频”和“GitCode”分类等等,那么该多么臃肿,对于使用者而言需要多写好多东西不说,还非常不易于维护。那怎么办?接下来就是简单工厂方法登场了。

简单工厂模式
public class EasyFactory {
    public static void main(String[] args) {
        EasyFactory easyFactory = new EasyFactory();
        easyFactory.BuildCategory(1);
        easyFactory.BuildCategory(2);
    }

    public void BuildCategory(int category) {
        switch (category) {
            case 1:
                System.out.println("建立类别:首页");
            case 2:
                System.out.println("建立类别:博客");
            case 3:
                System.out.println("建立类别:学习");
            case 4:
                System.out.println("建立类别:下载");
            case 5:
                System.out.println("建立类别:社区");
        }
    }
}

这好像看着舒服多了,对于使用者而言(main函数)仅需通过对应的值就能得到我要的分类了,使用者根本就不需要关注内部细节,也不需要知道到底有多少分类,仅需提供一个int值就能构造出想要的分类了。

这就完美了?不对把!根本就没有解决代码臃肿的问题,如果要扩展多个分类,还需要在switch语句中增加,那么BuildCategory方法会越来越庞大,一旦写错,程序就会崩溃了。

工厂方法模式

首先我们先建立一个工厂的接口,专门构造分类

public interface Factory {
   void createCategory();
}

而后,我们为每个分类都去实现这个工厂接口,这样就可以扩展出很多个分类工厂了

public static class IndexFactory implements Factory {
    @Override
    public void createCategory() {
        System.out.println("建立类别:首页");
    }
}

public static class BlogFactory implements Factory {
    @Override
    public void createCategory() {
        System.out.println("建立类别:博客");
    }
}

public static class StudyFactory implements Factory {
    @Override
    public void createCategory() {
        System.out.println("建立类别:学习");
    }
}

public static class DownloadFactory implements Factory {
    @Override
    public void createCategory() {
        System.out.println("建立类别:下载");
    }
}

public static class CommunityFactory implements Factory {
    @Override
    public void createCategory() {
        System.out.println("建立类别:社区");
    }
}

客户端代码

public static void main(String[] args) {
    Factory indexFactory = new IndexFactory();
    indexFactory.createCategory();

    Factory blogFactory = new BlogFactory();
    blogFactory.createCategory();

    Factory studyFactory = new StudyFactory();
    studyFactory.createCategory();
}

如果我们再去添加其他很多的分类,仅需实现工厂接口即可。这样既解决了简单工厂臃肿的问题,而且这里还遵循了设计模式的“开闭原则”,对扩展开放(实现工厂接口), 对修改关闭(新增分类修改BuildCategory方法)。

GOF对工厂方法模式的定义:工厂方法模式定义了一个创建对象的接口,但由子类决定实例化哪个类。工厂方法将对象的创建延迟到子类。

抽象工厂模式

我现在想仿CSDN也做个网站,那么就针对分类而言,虽然分类都一样,但是分类下的功能和CSDN有区别,怎么办?还像工厂模式一样,开始扩展,比如

public static class DirosIndexFactory implements Factory {
    @Override
    public void createCategory() {
        System.out.println("建立Diros的专属类别:首页");
    }
}

public static class DirosBlogFactory implements Factory {
    @Override
    public void createCategory() {
        System.out.println("建立Diros的专属类别:博客");
    }
}

我的专属就有5个和CSDN一样的分类,假如又有其他人也要模仿,虽然符合了开闭原则那么工厂类的数量会暴增的!后期还是不好维护。仔细思考下,既然分类都是人划分的,那同一功能点下应该属于一个系列。而抽象工厂解决的就是产品族创建的问题,它将同一系列产品的创建提取到了抽象工厂中。我们可以按照建站人创建不同分类族工厂:

public interface Factory {
    void createIndex();
    void createBlog();
    void createStudy();
    void createDownload();
    void createCommunity();
}

接下来,我们就可以嗨皮的创建自己的专属分类工厂了~~

public static class DirosCategory implements Factory {
    @Override
    public void createIndex() {
        System.out.println("建立Diros的专属类别:首页");
    }

    @Override
    public void createBlog() {
        System.out.println("建立Diros的专属类别:博客");
    }

    @Override
    public void createStudy() {
        System.out.println("建立Diros的专属类别:学习");
    }

    @Override
    public void createDownload() {
        System.out.println("建立Diros的专属类别:下载");
    }

    @Override
    public void createCommunity() {
        System.out.println("建立Diros的专属类别:社区");
    }
}

public static class SuperManCategory implements Factory {
    @Override
    public void createIndex() {
        System.out.println("建立SuperMan的专属类别:首页");
    }

    @Override
    public void createBlog() {
        System.out.println("建立SuperMan的专属类别:博客");
    }

    @Override
    public void createStudy() {
        System.out.println("建立SuperMan的专属类别:学习");
    }

    @Override
    public void createDownload() {
        System.out.println("建立SuperMan的专属类别:下载");
    }

    @Override
    public void createCommunity() {
        System.out.println("建立SuperMan的专属类别:社区");
    }
}

我建立了Diros和SuperMan的专属分类网站,最后是客户端运行的代码:

public static void main(String[] args) {
    Factory dirosFactory = new DirosCategory();
    dirosFactory.createBlog();
    dirosFactory.createDownload();
    dirosFactory.createIndex();

    Factory superManFactory = new DirosCategory();
    superManFactory.createCommunity();
    superManFactory.createStudy();
}

GOF对抽象工厂方法模式的定义:抽象工厂模式提供一个创建一系列相关或互相依赖对象的接口,而无需指定它们具体的类。

不过抽象工厂模式也有它的缺点,如果我再新增一种分类,那么无疑就要修改Factory的接口了,对应所有的实现类都要修改,这好像违反了开闭原则了。

总结

简单工厂模式简单容易使用,适合比较少的产品创建,缺点则是不符合开闭原则

工厂模式对于扩展新产品提供了便捷操作仅需实现工厂接口即可,缺点是如果产品多,实现类就会暴增

抽象工厂模式很好解决了产品族创建的问题,但是不太符合开闭原则,不过它也有解决办法,就是利用反射去创建(Go语言,c++都有反射)

总之这三种工厂模式都各有用途,在不同的场景应选用不同的模式

demo地址:GitCode - 全球开发者的开源社区,开源代码托管平台

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Diros2025

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值