设计模式:工厂模式

建议大家不要看我的文章,我写的比较随性,推荐神作地址,通俗易懂:

https://blog.csdn.net/LoveLion/article/details/9319181

https://blog.csdn.net/LoveLion/article/details/9319323

https://blog.csdn.net/LoveLion/article/details/9319423

https://blog.csdn.net/LoveLion/article/details/9319481

https://blog.csdn.net/LoveLion/article/details/9319571

工厂模式一般分为三种:简单工厂模式,工厂方法模式,抽象工厂模式。

工厂模式的诞生:把具体的业务逻辑交由工厂类去完成,程序体本身并不关注这类逻辑的创建和销毁。减少了程序的耦合性和提高了程序的可维护性,符合了程序设计的开闭原则。

简单工厂模式:具体对象的实例由工厂去创建

GOF的23种设计模式并不区分简单工厂模式,和工厂方法模式同属一个模式。

例子:BMW品牌需要生产汽车,汽车的型号为BMW277,BMW520,BMW666。BMW最开始计划按部就班的生产:

public class BMW {

    public static void main(String[] args) {
        // 生产BMW277
        // 1.组装引擎。
        //2.组长轮胎
        //3.组长地盘

        //生产BMW520
        // 1.组装引擎。
        //2.组长轮胎
        //3.组长地盘

        //生产BMW666
        // 1.组装引擎。
        //2.组长轮胎
        //3.组长地盘
    }
}

就这样一个一个生产完了,突然BMW公司发现,若其中一个环节出问题,其剩下的步骤就无法继续执行,而且若增加新的型号时,必须在生产的主要业务逻辑代码中添加额外的代码,并且所有业务逻辑都放在了一个块中执行,大大的限制了以后生产的灵活性。于是BMW决定建造额外的工厂去专门做这些事,主业务(也就是main方法)去告诉工厂需要什么型号的汽车即可,不参与具体的生产流程

例:

定义一个BMW的抽象类或者接口,所有型号的汽车都必须继承或者实现该类,相当于BMW总部,总部告诉工厂需要生产什么型号的汽车:

public interface BMW {

    // 组装
    public void create();
}

BMW277:

public class BMW277 implements BMW{

    @Override
    public void create() {
        //组装流程在此进行
    }
}

BMW520:

public class BMW520 implements BMW{

    @Override
    public void create() {
       // 组长流程再次进行
    }
}

BMW666:

public class BMW666 implements BMW{

    @Override
    public void create() {
      // 组长流程在此进行  
    }
}

创建简单工厂:

public class BMWFactory {

    public static BMW getBMW(String type){
        switch (type) {
            case "277":
                return new BMW277();
            case "520":
                return new BMW520();
            case "666":
                return new BMW666(); 
            default:
                return null;
        }
    }
}

总部调用工厂方法生产对应型号的汽车:

public class Test {

    public static void main(String[] args) {
        // 简单工厂模式
        BMW bmw520 = BMWFactory.getBMW("520");
        BMW bmw277 = BMWFactory.getBMW("277");

       
    }
}

此时若需要增加新的信号,则只需要实现BMW接口,并且在工厂内中增加响应的case分支即可,既不影响主程序main的执行,还对主程序进行了解耦操作。

后来BMW的汽车型号越来越多,如果继续这样增加下去,还需要在工厂类中增加代码,违背了程序的开闭原则,即是禁止修改,提倡扩展。于是BMW想出了更好的办法:

工厂方法模式:

即以前的代码写好后就写好了,不会对以前的代码做任何改动,只需要在之前的代码之上继续扩展即可

例:在以上的基础上推倒已有的工厂,重新建造工厂总部:抽象工厂或者工厂接口:

public abstract class AbstractFactory {

    public abstract BMW getBmw();
}

然后开分厂,每个分厂负责生产对应的型号的汽车:

生产277的工厂:

public class BMW277Factory extends AbstractFactory{
    @Override
    public BMW getBmw() {
        return new BMW277();
    }
}

生产520的工厂:

public class BMW520Factory extends AbstractFactory{
    @Override
    public BMW getBmw() {
        return new BMW520();
    }
}

生产666的工厂:

public class BMW666Factory extends AbstractFactory{
    @Override
    public BMW getBmw() {
        return new BMW666();
    }
}

每个型号的汽车交友各自的工厂去生产,这样在增加新的型号的汽车时,只需要继承AbstractFactory在创建一个生产对应型号的汽车即可。

这样就符合了程序设计的开闭原则。但是问题又出现了,若之后增加的型号越来越多,则会出现大量的汽车类和汽车工厂,而且此方法无法应对更复杂的业务场景:

BMW决定为每个型号的汽车都分别安装不同型号的空调和行车记录仪,277安装的空调型号为Cool277和行车记录仪Video277,

520安装型号为Cool520和行车记录仪Video520,666同理。于是决定彩用抽象工厂模式:

产品类型:BMW-->BMW277,BMW520,BMW666

                  Cool ->Cool277,Cool520,Cool666

                Video->Video277,Video520,Video666

产品族:BMW277,Cool277,Video277

              BMW520,Cool520,Video520

             BMW666,Cool666,Video666

同一个工厂可以生成对应型号的产品族即可:

例子:

空调抽象类

public abstract class Cool {
}
277空调:
public class Cool277 extends Cool{
}

520空调

public class Cool520 extends Cool{
}

666空调:

public class Cool666 extends Cool{
}

行车记录仪抽象类:

public abstract class Video {
}

277:

public class Video277 extends Video{
}

520:

public class Video520 extends Video{
}

666:

public class Video666 extends Video{
}

抽象工厂族:

public abstract class Factory {

    // 制造汽车
    abstract BMW getBmw();

    // 制造空调
    abstract Cool getCool();

    // 制造行车记录仪
    abstract Video getVideo();
}

277产品族工厂类:

public class Factory277 extends Factory{
    @Override
    BMW getBmw() {
        return new BMW277();
    }

    @Override
    Cool getCool() {
        return new Cool277();
    }

    @Override
    Video getVideo() {
        return new Video277();
    }
}

520产品族工厂类:

public class Factory520 extends Factory{
    @Override
    BMW getBmw() {
        return new BMW520();
    }

    @Override
    Cool getCool() {
        return new Cool520();
    }

    @Override
    Video getVideo() {
        return new Video520();
    }
}

666产品族工厂类:

public class Factory666 extends Factory{
    @Override
    BMW getBmw() {
        return new BMW666();
    }

    @Override
    Cool getCool() {
        return new Cool666();
    }

    @Override
    Video getVideo() {
        return new Video666();
    }
}

主程序通知工厂制作相关型号汽车和空调:

public class Test {

    public static void main(String[] args) {
       // 277型号产品族
        Factory factory277 = new Factory277();
        BMW bmw277 = factory277.getBmw();
        Cool cool277 = factory277.getCool();
        Video video277 = factory277.getVideo();

        // 520型号产品族
        Factory factory520 = new Factory520();
        BMW bmw520 = factory520.getBmw();
        Cool cool520 = factory520.getCool();
        Video video520 = factory520.getVideo();

        // 666型号产品族
        Factory factory666 = new Factory666();
        BMW bmw666 = factory666.getBmw();
        Cool cool666 = factory666.getCool();
        Video video666 = factory666.getVideo();
    }
}

此模式在framework中常用到,对于产品型号来说,扩展符合开闭原则,应为不需要修改源代码,直接继承扩展即可。但是对于产品族的扩展,却不符合开闭原则。若增加了新的配件,比如汽车加湿器,则需要在源代码中加入新的代码。

具体用哪个模式,参照实际设计中的业务场景,找到一款最符合的设计模式。



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值