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

简介:

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

举例:每个汽车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、生成不同操作系统的程序。

原文地址:https://www.cnblogs.com/hellxz/p/8449522.html