• 【设计模式学习笔记】 之 抽象工厂模式


    简介:

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

    举例:每个汽车4s店和某个品牌工厂之间的关系,每个汽车4s店只会卖同一品牌的汽车,但是如果这一品牌汽车销量不好,效益不佳,那么4s店可以更换进货的工厂,从而更换其售卖的品牌。

    分析:每个品牌的汽车都有一个品牌工厂,这些工厂都有一个生产汽车的方法,4s店中应持有工厂的引用,所以这些汽车工厂都应该实现一个汽车工厂接口,这个4s店中持有汽车工厂的接口,以便更换汽车工厂改变品牌。

    实现:

    汽车工厂是用来生产汽车的,所以首先应该有一个汽车接口,所有汽车都有一个run方法

    1 package com.mi.abstractfactory;
    2 
    3 public interface Car {
    4 
    5     void run();
    6 }

    实现这个接口创建一款汽车

    package com.mi.abstractfactory;
    
    /**
     * 沃尔沃汽车
     */
    public class VolvoCar implements Car{
    
        @Override
        public void run() {
            System.out.println("沃尔沃:别赶路,去感受路!");
        }
    
    }

    有了汽车类了,这样就可以使用工厂来批量生产了,创建一个汽车工厂接口,其中包含一个生产汽车的方法

     1 package com.mi.abstractfactory;
     2 
     3 /**
     4  * 汽车工厂接口
     5  * @author hellxz
     6  */
     7 public interface AbstractCarFactory {
     8     
     9     //接口中所有的没有使用权限修饰符的方法,都是public static final的
    10     Car getCar();
    11 }

    2.实现一个品牌汽车工厂

     1 package com.mi.abstractfactory;
     2 /**
     3  * 沃尔沃汽车工厂
     4  */
     5 public class VolvoCarFactory implements AbstractCarFactory {
     6 
     7     @Override
     8     public VolvoCar getCar() {
     9         return new VolvoCar();
    10     }
    11 
    12 }

    3.创建一个汽车4s店,这个店铺需要有一个卖车的方法saleCar(),并持有一个工厂的引用

     1 package com.mi.abstractfactory;
     2 
     3 public class SSSS {
     4 
     5     /**
     6      * 实现抽象工厂对象的 注入有两种方式,一种是set设值注入,构造方法,都持有接口的引用
     7      */
     8     //持有引用,可以根据多态性,传入该接口的实现类型,从而实现不同的效果
     9     private AbstractCarFactory carFactory;
    10     
    11     public Car saleCar() {
    12         return carFactory.getCar(); //抽象工厂获取方式得到car对象,可以是car的子类,多态
    13     }
    14 
    15     public void setCarFactory(AbstractCarFactory carFactory) {
    16         this.carFactory = carFactory;
    17     }
    18     
    19 }

    为了能看出来更换工厂的效果,同理创建一个Benz汽车的类和工厂

     1 package com.mi.abstractfactory;
     2 
     3 /**
     4  * 奔驰汽车
     5  * @author hellxz
     6  */
     7 public class BenzCar implements Car {
     8 
     9     @Override
    10     public void run() {
    11         System.out.println("奔驰:随时准备好上路疾驶!");
    12     }
    13 
    14 }
     1 package com.mi.abstractfactory;
     2 
     3 /**
     4  * 奔驰汽车工厂
     5  * @author hellxz
     6  */
     7 public class BenzCarFactory implements AbstractCarFactory {
     8 
     9     @Override
    10     public BenzCar getCar() {
    11         return new BenzCar();
    12     }
    13     
    14     // 也可以这样写,返回父类的引用,因为多态(动态绑定),在运行的时候会确定该类型 的具体类型
    15     /*    public Car getCar() {
    16      *        return new BenzCar();
    17      *    }
    18      */
    19 
    20 }

    测试类

     1 package com.mi.abstractfactory;
     2 
     3 /**
     4  * @author hellxz
     5  */
     6 public class Test {
     7 
     8     public static void main(String[] args) {
     9         SSSS ssss = new SSSS();
    10 //        ssss.setCarFactory(new BenzCarFactory()); //奔驰的工厂
    11         ssss.setCarFactory(new VolvoCarFactory()); //沃尔沃的工厂
    12         Car car = ssss.saleCar();
    13         car.run();
    14     }
    15 }

    输出:

    沃尔沃:别赶路,去感受路!

    测试更换工厂,打开注释行,注释掉沃尔沃的工厂行

    输出:

    奔驰:随时准备好上路疾驶!

    总结:

    主要解决:主要解决接口选择的问题。

    何时使用:一个系统中有多个系列可选择的情况,每次只能选择其中一系列

    优点:

    1. 当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
    2. 降低耦合

    缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 接口 里加代码,又要在具体的里面加代码。

    使用场景: 1、更换一整套的产品  2、生成不同操作系统的程序。

  • 相关阅读:
    PHP中过滤数组中的元素
    cookie中文乱码解决(php/js)
    Ubuntu系统tar克隆
    磁盘IO性能监控(Linux 和 Windows)
    远程桌面由于帐户限制你无法登录问题
    SAP中关于用户IP信息的获取
    选择界面制作按钮
    ALV常用参数详细描述
    销售订单、外向交货单、交货 bapi
    abap 常用表
  • 原文地址:https://www.cnblogs.com/hellxz/p/8449522.html
Copyright © 2020-2023  润新知