设计模式学习(五)抽象工厂模式

介绍

抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。

类图说明

延用我们上一篇工厂模式的例子,车工厂造车的例子,我们做下延伸画出来的类图如下:
在这里插入图片描述
做下简单说明,我们首先创建了两个工厂类,一个是创造不同等级的宝马车工厂类,另外一个是创建不同等级的奔驰车工厂类,然后通过定义一个抽象类,该抽象类提供两个方法,一个是创建宝马车,一个是创建奔驰车,然后再定义一个工厂类的生产者,去对抽象类提供的两个方法进行具体的实现,最后面对于客户端来说,他们想要创造提取宝马或者奔驰的那种等级的车,通过该实现类去调用即可。简单一句话来说,抽象工厂模式是工厂模式的一个升级,增加了不同维度的概念进去,使得需要一个抽象类对多个工厂类再多做一层封装,但最终达到的效果和普通工厂模式是一致的,客户端不需要关心具体的实现,只需要告知自己的需求去调用接口获取即可。

代码示例

文件结构如图所示:
在这里插入图片描述
具体类的实现:

public interface BMW {
    
    
    void getName();
    void getColor();
}
public class HighBMW implements BMW {
    
    
    @Override
    public void getName() {
    
    
        System.out.println("我是高端宝马车");
    }

    @Override
    public void getColor() {
    
    

    }
}
public interface Benz {
    
    
    void getName();
    void getColor();
}
public class HighBenz implements Benz {
    
    
    @Override
    public void getName() {
    
    
        System.out.println("我是高端奔驰车");
    }

    @Override
    public void getColor() {
    
    

    }
}
/**
 * 抽象工厂
 */
public class BenzFactory {
    
    

        public static <T extends Benz> T createBenz(Class<T> c){
    
    
            Benz benz = null;
            try {
    
    
                benz = (Benz) Class.forName(c.getName()).newInstance();
            } catch (Exception e) {
    
    
                System.out.println("造奔驰车失败");
            }
            return (T)benz;
        }

}
public class BMWFactory {
    
    

        public static <T extends BMW> T createBMW(Class<T> c){
    
    
            BMW bmw = null;
            try {
    
    
                bmw = (BMW) Class.forName(c.getName()).newInstance();
            } catch (Exception e) {
    
    
                System.out.println("造宝马车失败");
            }
            return (T)bmw;
        }

}
/**
 * 抽象工厂
 */
public abstract class AbstractFactory {
    
    
    public abstract <T extends BMW> T createBMW(Class<T> c);
    public abstract <T extends Benz> T createBenz(Class<T> c);
}
public class FactoryProducer extends AbstractFactory {
    
    

    @Override
    public <T extends BMW> T createBMW(Class<T> c) {
    
    
        BMW bmw = BMWFactory.createBMW(c);
        return (T)bmw;
    }

    @Override
    public <T extends Benz> T createBenz(Class<T> c) {
    
    
        Benz benz = BenzFactory.createBenz(c);
        return (T)benz;
    }
}
public class AbstractFactoryPattern {
    
    
    public static void main(String[] args){
    
    

        FactoryProducer factoryProducer = new FactoryProducer();

        /**
         * 创建高端产品车
         * 如果想将具体等级的工厂类开放给客户端,可将factory修改
         * 例如场景中就可以直接创建三类工厂类
         * 1、高端车工厂
         * 2、中端车工厂
         * 3、低端车工厂
         * 每类分别提供创建各个种类的等级车方法
         */
        HighBenz highBenz = factoryProducer.createBenz(HighBenz.class);
        highBenz.getName();
        HighBMW highBMW = factoryProducer.createBMW(HighBMW.class);
        highBMW.getName();

        /**
         * 创建低端产品车
         */
        MidBenz midBenz = factoryProducer.createBenz(MidBenz.class);
        midBenz.getName();
        MidBMW midBMW = factoryProducer.createBMW(MidBMW.class);
        midBMW.getName();

    }
}

代码有点多,可以参照类图来看代码,这里就不做具体的介绍了。
代码运行结果如下:
在这里插入图片描述

应用场景

  • QQ 换皮肤,一整套一起换
  • 生成不同操作系统的程序

优缺点

优点

  • 封装性,每个产品的实现类不是高层模块要关心的,它要关心的是什么?是接口,是
    抽象,它不关心对象是如何创建出来,这由谁负责呢?工厂类,只要知道工厂类是谁,我就
    能创建出一个需要的对象,省时省力,优秀设计就应该如此。
  • 当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。

缺点

  • 产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。以我们车的例子来说,如果要加一个特斯拉产品进去,那么就需要在我们的抽象类里添加一个造特斯拉的方法,相应的实现类也要被修改,这不符合前文我们提到的开闭原则,需要在原类里头做一系列的修改,风险较高。相对而言如果是增加宝马后者奔驰车的某种车等级方法,相对而言比较容易,添加对应等级的车的实现类即可,不用改造已经实现的任何方法。概括来说就是横向扩展容易,纵向扩展难。

Guess you like

Origin blog.csdn.net/he_cha_bu/article/details/114456419