设计模式三:工厂模式


工厂模式包括简单工厂模式、工厂方法模式和抽象工厂模式,其中后两者属于23中设计模式

各种模式中共同用到的实体对象类:

//汽车类:宝马X3/X5/X7;发动机类:B48TU、B48
    
//宝马汽车接口
public interface BMWCar {
    void show();
}

//发动机接口
public interface Engine {
    void show();
}

//宝马X3
public class BMWX3 implements BMWCar {
    @Override
    public void show() {
        System.out.println("华晨宝马X3:39.96-48.69万");
    }
}

//宝马X5
public class BMWX5 implements BMWCar {
    @Override
    public void show() {
        System.out.println("华晨宝马X5:58.75-80万");
    }
}

//宝马X7
public class BMWX7 implements BMWCar {
    @Override
    public void show() {
        System.out.println("华晨宝马X3:89.35-102.25万");
    }
}

//B48TU发动机
public class B48TUEngine implements Engine {
    @Override
    public void show() {
        System.out.println("B48TU:涡轮增压 压缩比 11:1");
    }
}

//B48发动机
public class B48Engine implements Engine {
    @Override
    public void show() {
        System.out.println("B48:涡轮增压 压缩比 10.2:1");
    }
}

1、简单工厂模式

  • 模型

​ 用户只需要使用汽车生产工厂,告诉其想要生产的车型,具体生产细节不需要了解即可得到希望车型
在这里插入图片描述

  • 实现
//简单工厂类
public class BMWCarFactory {
    public static BMWCar buy(String carName){
        switch (carName){
            case "BMWX5":
                return new BMWX5();
            case "BMWX3":
                return new BMWX3();
            default:
                return null;
        }
    }
}

//测试
public class Consumer {
    public static void main(String[] args) {
        BMWCar bmwCar = BMWCarFactory.buy("BMWX5");
        if (bmwCar == null){
            System.out.println("无该车型");
        }
        assert bmwCar != null;
        bmwCar.show();
    }
}

简单工厂模式:

再添加一个宝马产品,就要修改factory类

1、使用进阶版简单工厂模式

2、使用工厂方法模式,即有自工厂生产对应车型,X5由X5Factory生产,X3由X3Factory生产,在添加一种车型,则对应添加一个工厂类型

简单工厂模式适用于的场景:

1、适用 于工厂类负责创建的对象较少的场景,

2、且客户端只需要传入工厂类的参数,对于如何创 建对象的逻辑不需要关心。

简单工厂模式缺点:

1、工厂类的职业相对过重,增加新的产品时需要修改工厂类的判断逻辑,违背开闭原则

2、不易于扩展过于复杂的产品结构

2、进阶版简单工厂模式

//工厂类
public class BMWFactory {
    public static <T> T buy(Class<T> clazz){
        try {
            return clazz.newInstance();
        } catch (Exception e) {
            return null;
        }
    }
}

//测试
public class Consumer {
    public static void main(String[] args) {
        BMWCar newCar = BMWFactory.buy(BMWX3.class);
        if (newCar == null){
            System.out.println("无该车型");
        }
        newCar.show();
    }
}

3、工厂方法模式

  • 模型
    在这里插入图片描述
//宝马工厂接口
public interface BMWCarFactory {
    BMWCar buy();
}

//BMWX3工厂
public class BMWX3CarFactory implements BMWCarFactory {
    @Override
    public BMWCar buy() {
        //可在这里做一定处理,对客户不可见,即对客户是透明的
        //......
        return new BMWX3();
    }
}

//BMWX5工厂
public class BMWX5CarFactory implements BMWCarFactory {
    @Override
    public BMWCar buy() {
        //可在这里做一定处理,对客户不可见,即对客户是透明的
        //......
        return new BMWX5();
    }
}

//BMWX7工厂
public class BMWX7CarFactory implements BMWCarFactory {
    @Override
    public BMWCar buy() {
        //可在这里做一定处理,对客户不可见,即对客户是透明的
        //......
        return new BMWX7();
    }
}

//测试
public class Consumer {
    public static void main(String[] args) {
        BMWCar bmwCar = BMWCarFactory.buy("BMWX5");
        if (bmwCar == null){
            System.out.println("无该车型");
        }
        assert bmwCar != null;
        bmwCar.show();
    }
}

工厂方法模式的适用场景:

1、创建对象需要大量重复的代码

2、客户端(应用层)不依赖于产品类实例如何被创建、实现等细节,一个类通过其子类来指定创建哪个对象。

工厂方法模式的优点:

1、用户只关系所需产品对应的工厂,无须关心创建细节。

2、加入新产品符合开闭原则,提高了系统的可扩展性。

工厂方法模式的缺点:

1、类的个数容易过多,增加了代码结构的复杂度。

2、增加了系统的抽象性和理解难度。

工厂方法模式:

如果处了汽车之外,新增加发动机产品 B48TU发动机(X5搭载) 和 B48发动机(X3搭载)

那么需要新增发动机工厂接口、B48TU工厂、B48工厂、发动机接口、B48TU发动机、B48发动机

如下图所示
在这里插入图片描述

4、抽象工厂模式

  • 模型

在这里插入图片描述

  • 实现
//宝马工厂接口
public interface BMWFactory {
    BMWCar buyCar();
    Engine buyEngine();
}

//宝马X3工厂
public class BMWX3Factory implements BMWFactory {
    @Override
    public BMWCar buyCar() {
        return new BMWX3();
    }

    @Override
    public Engine buyEngine() {
        return new B48Engine();
    }
}

//宝马X5工厂
public class BMWX5Factory implements BMWFactory {
    @Override
    public BMWCar buyCar() {
        return new BMWX5();
    }

    @Override
    public Engine buyEngine() {
        return new B48TUEngine();
    }
}

//测试
public class Consumer {
    public static void main(String[] args) {
        BMWFactory factory = new BMWX3Factory();

        factory.buyCar().show();
        factory.buyEngine().show();
    }
}

抽象工厂模式:

将不同种类,同一等级的类放在一个工厂加工

但是新增产品时需要修改工厂类

抽象工厂模式使用场景:

1、客户端(应用层)不依赖于产品类实例如何被创建,实现等细节。

2、强调一系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量重复的代码。

3、提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体的实现。

抽象工厂模式优点:

1、具体产品在应用层代码隔离,无须关系创建细节。

2、将一个系列的产品族统一到一起创建。

抽象工厂模式缺点:

1、规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口。

2、增加了系统的抽象性和理解难度。

5、spring中的工厂模式

Calendar.getInstance()   //简单工厂模式
LoggerFactory、BeanFactory、FactoryBean   //工厂方法模式
Calendar
if (aLocale.hasExtensions()) {
    String caltype = aLocale.getUnicodeLocaleType("ca");
    if (caltype != null) {
        switch (caltype) {
            case "buddhist":
                cal = new BuddhistCalendar(zone, aLocale);
                break;
            case "japanese":
                cal = new JapaneseImperialCalendar(zone, aLocale);
                break;
            case "gregory":
                cal = new GregorianCalendar(zone, aLocale);
                break;
        }
    }
}
BeanFactory
public class TestBeanFactory {

    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        // bean 的定义(class, scope, 初始化, 销毁)
        AbstractBeanDefinition beanDefinition =
                BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();
        beanFactory.registerBeanDefinition("config", beanDefinition);

        // 给 BeanFactory 添加一些常用的后处理器
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);

        beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().forEach(beanFactoryPostProcessor -> {
            beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
        });

        // 打印BeanFactory中Bean
        for (String name : beanFactory.getBeanDefinitionNames()) {
            System.out.println(name);
        }
    }

    @Configuration
    static class Config {
        @Bean
        public Bean1 bean1() {
            return new Bean1();
        }

        @Bean
        public Bean2 bean2() {
            return new Bean2();
        }
    }

    static class Bean1 {
        private static final Logger log = LoggerFactory.getLogger(Bean1.class);

        public Bean1() {
            log.debug("构造 Bean1()");
        }

        @Autowired
        private Bean2 bean2;

        public Bean2 getBean2() {
            return bean2;
        }
    }

    static class Bean2 {
        private static final Logger log = LoggerFactory.getLogger(Bean2.class);

        public Bean2() {
            log.debug("构造 Bean2()");
        }
    }
}
  • 15
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值