zoukankan      html  css  js  c++  java
  • 设计模式08---设计模式之抽象工厂模式(Abstract Factory)

    1.场景模拟

    举个生活中常见的例子:组装电脑,我们在组装电脑的时候,通常要选择一系列的配件,比如选择CPU时候,需要注意品牌,型号,针脚数目,主频,只有这些都确定下来,才能确定一个CPU。同样,主板也是这样的。对于装机工程师而言,他只知道装一台电脑需要使用相应的配件,具体的配件,还是由客户说了算。

    2.一般的解决方案(简单工厂)

    2.1CPU接口

    package demo06.abstractfactory.example1;
    
    
    /**
     * CPU的接口
     */
    public interface CPUApi {
    	/**
    	 * 示意方法,CPU具有运算的功能
    	 */
    	public void calculate();
    }

    2.2主板接口

    package demo06.abstractfactory.example1;
    
    /**
     * 主板的接口
     */
    public interface MainboardApi {
    	/**
    	 * 示意方法,主板都具有安装CPU的功能
    	 */
    	public void installCPU();
    }

    2.3 Inter CPU实现

    package demo06.abstractfactory.example1;
    
    
    /**
     * Intel的CPU实现
     */
    public class IntelCPU implements CPUApi {
    	/**
    	 * CPU的针脚数目
    	 */
    	private int pins = 0;
    
    
    	/**
    	 * 构造方法,传入CPU的针脚数目
    	 * 
    	 * @param pins
    	 *            CPU的针脚数目
    	 */
    	public IntelCPU(int pins) {
    		this.pins = pins;
    	}
    
    
    	public void calculate() {
    		System.out.println("now in Intel CPU,pins=" + pins);
    	}
    }

    2.4 AMD的CPU实现

    package demo06.abstractfactory.example1;
    
    
    /**
     * AMD的CPU实现
     */
    public class AMDCPU implements CPUApi {
    	/**
    	 * CPU的针脚数目
    	 */
    	private int pins = 0;
    
    
    	/**
    	 * 构造方法,传入CPU的针脚数目
    	 * 
    	 * @param pins
    	 *            CPU的针脚数目
    	 */
    	public AMDCPU(int pins) {
    		this.pins = pins;
    	}
    
    
    	public void calculate() {
    		System.out.println("now in AMD CPU,pins=" + pins);
    	}
    }

    2.5技嘉的主板实现

    package demo06.abstractfactory.example1;
    
    
    /**
     * 技嘉的主板
     */
    public class GAMainboard implements MainboardApi {
    	/**
    	 * CPU插槽的孔数
    	 */
    	private int cpuHoles = 0;
    
    
    	/**
    	 * 构造方法,传入CPU插槽的孔数
    	 * 
    	 * @param cpuHoles
    	 *            CPU插槽的孔数
    	 */
    	public GAMainboard(int cpuHoles) {
    		this.cpuHoles = cpuHoles;
    	}
    
    
    	public void installCPU() {
    		System.out.println("now in GAMainboard,cpuHoles=" + cpuHoles);
    	}
    }

    2.6微星的主板

    package demo06.abstractfactory.example1;
    
    
    /**
     * 微星的主板
     */
    public class MSIMainboard implements MainboardApi {
    	/**
    	 * CPU插槽的孔数
    	 */
    	private int cpuHoles = 0;
    
    
    	/**
    	 * 构造方法,传入CPU插槽的孔数
    	 * 
    	 * @param cpuHoles
    	 *            CPU插槽的孔数
    	 */
    	public MSIMainboard(int cpuHoles) {
    		this.cpuHoles = cpuHoles;
    	}
    
    
    	public void installCPU() {
    		System.out.println("now in MSIMainboard,cpuHoles=" + cpuHoles);
    	}
    }

    2.7创建CPU工厂

    package demo06.abstractfactory.example1;
    /**
     * 创建CPU的简单工厂
     */
    public class CPUFactory {
    	/**
    	 * 创建CPU接口对象的方法
    	 * @param type 选择CPU类型的参数
    	 * @return CPU接口对象的方法
    	 */
    	public static CPUApi createCPUApi(int type){
    		CPUApi cpu = null;
    		//根据参数来选择并创建相应的CPU对象
    		if(type==1){
    			cpu = new IntelCPU(1156);
    		}else if(type==2){
    			cpu = new AMDCPU(939);
    		}
    		return cpu;
    	}	
    }

    2.8创建主板工厂

    package demo06.abstractfactory.example1;
    
    
    /**
     * 创建主板的简单工厂
     */
    public class MainboardFactory {
    	/**
    	 * 创建主板接口对象的方法
    	 * 
    	 * @param type
    	 *            选择主板类型的参数
    	 * @return 主板接口对象的方法
    	 */
    	public static MainboardApi createMainboardApi(int type) {
    		MainboardApi mainboard = null;
    		// 根据参数来选择并创建相应的主板对象
    		if (type == 1) {
    			mainboard = new GAMainboard(1156);
    		} else if (type == 2) {
    			mainboard = new MSIMainboard(939);
    		}
    		return mainboard;
    	}
    }

    2.9工程师实现代码

    package demo06.abstractfactory.example1;
    
    
    /**
     * 装机工程师的类
     */
    public class ComputerEngineer {
    	/**
    	 * 定义组装机器需要的CPU
    	 */
    	private CPUApi cpu = null;
    	/**
    	 * 定义组装机器需要的主板
    	 */
    	private MainboardApi mainboard = null;
    
    
    	/**
    	 * 装机过程
    	 * 
    	 * @param cpuType
    	 *            客户选择所需CPU的类型
    	 * @param mainboardType
    	 *            客户选择所需主板的类型
    	 */
    	public void makeComputer(int cpuType, int mainboardType) {
    		// 1:首先准备好装机所需要的配件
    		prepareHardwares(cpuType, mainboardType);
    		// 2:组装机器
    
    
    		// 3:测试机器
    
    
    		// 4:交付客户
    	}
    
    
    	/**
    	 * 准备装机所需要的配件
    	 * 
    	 * @param cpuType
    	 *            客户选择所需CPU的类型
    	 * @param mainboardType
    	 *            客户选择所需主板的类型
    	 */
    	private void prepareHardwares(int cpuType, int mainboardType) {
    		// 这里要去准备CPU和主板的具体实现,为了示例简单,这里只准备这两个
    		// 可是,装机工程师并不知道如何去创建,怎么办呢?
    
    
    		// 直接找相应的工厂获取
    		this.cpu = CPUFactory.createCPUApi(cpuType);
    		this.mainboard = MainboardFactory.createMainboardApi(mainboardType);
    
    
    		// 测试一下配件是否好用
    		this.cpu.calculate();
    		this.mainboard.installCPU();
    	}
    }

    2.90客户端测试

    package demo06.abstractfactory.example1;
    
    
    public class Client {
    	public static void main(String[] args) {
    		// 创建装机工程师对象
    		ComputerEngineer engineer = new ComputerEngineer();
    		// 告诉装机工程师自己选择的配件,让装机工程师组装电脑
    		engineer.makeComputer(1, 2);
    	}
    }

    3.问题:

    问题出现了:如果client传入的参数时1,2,那么装机不匹配就会失败,所以就会出现问题,如何解决呢?

    4.解决方法(抽象工厂模式)

    4.1模式定义:

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

    4.2模式的结构和说明

     

    5.示例代码(抽象工厂模式)

    5.1抽象工厂接口

    package demo06.abstractfactory.example2;
    
    
    /**
     * 抽象工厂的接口,声明创建抽象产品对象的操作
     */
    public interface AbstractFactory {
    	/**
    	 * 示例方法,创建抽象产品A的对象
    	 * 
    	 * @return 抽象产品A的对象
    	 */
    	public AbstractProductA createProductA();
    
    
    	/**
    	 * 示例方法,创建抽象产品B的对象
    	 * 
    	 * @return 抽象产品B的对象
    	 */
    	public AbstractProductB createProductB();
    }

    5.2产品A接口

    package demo06.abstractfactory.example2;
    
    
    /**
     * 抽象产品A的接口
     */
    public interface AbstractProductA {
    	// 定义抽象产品A相关的操作
    }

    5.3产品B接口

    package demo06.abstractfactory.example2;
    
    
    /**
     * 抽象产品B的接口
     */
    public interface AbstractProductB {
    	// 定义抽象产品B相关的操作
    }

    5.4产品A实现

    package demo06.abstractfactory.example2;
    
    
    /**
     * 产品A的具体实现
     */
    public class ProductA1 implements AbstractProductA {
    	// 实现产品A的接口中定义的操作
    }
    
    
    package demo06.abstractfactory.example2;
    
    
    /**
     * 产品A的具体实现
     */
    public class ProductA2 implements AbstractProductA {
    	// 实现产品A的接口中定义的操作
    }

    5.5产品B实现

    package demo06.abstractfactory.example2;
    
    
    /**
     * 产品B的具体实现
     */
    public class ProductB1 implements AbstractProductB {
    	// 实现产品B的接口中定义的操作
    }
    
    
    package demo06.abstractfactory.example2;
    
    
    /**
     * 产品B的具体实现
     */
    public class ProductB2 implements AbstractProductB {
    	// 实现产品B的接口中定义的操作
    }

    5.6具体工厂实现

    package demo06.abstractfactory.example2;
    
    
    /**
     * 具体的工厂实现对象,实现创建具体的产品对象的操作
     */
    public class ConcreteFactory1 implements AbstractFactory {
    
    
    	public AbstractProductA createProductA() {
    		return new ProductA1();
    	}
    	public AbstractProductB createProductB() {
    		return new ProductB1();
    	}
    }
    
    
    package demo06.abstractfactory.example2;
    
    
    /**
     * 具体的工厂实现对象,实现创建具体的产品对象的操作
     */
    public class ConcreteFactory2 implements AbstractFactory {
    
    
    	public AbstractProductA createProductA() {
    		return new ProductA2();
    	}
    	public AbstractProductB createProductB() {
    		return new ProductB2();
    	}
    }

    5.7客户端

    package demo06.abstractfactory.example2;
    
    
    public class Client {
    
    
    	public static void main(String[] args) {
    		// 创建抽象工厂对象
    		AbstractFactory af = new ConcreteFactory1();
    		// 通过抽象工厂来获取一系列的对象,如产品A和产品B
    		af.createProductA();
    		af.createProductB();
    	}
    }

    6.重写示例代码

    6.1结构图

     

    6.2抽象工厂接口

    package demo06.abstractfactory.example3;
    
    
    /**
     * 抽象工厂的接口,声明创建抽象产品对象的操作
     */
    public interface AbstractFactory {
    	/**
    	 * 创建CPU的对象
    	 * 
    	 * @return CPU的对象
    	 */
    	public CPUApi createCPUApi();
    
    
    	/**
    	 * 创建主板的对象
    	 * 
    	 * @return 主板的对象
    	 */
    	public MainboardApi createMainboardApi();
    }

    6.3装机方案一

    package demo06.abstractfactory.example3;
    
    
    /**
     * 装机方案一:Intel 的CPU + 技嘉的主板 这里创建CPU和主板对象的时候,是对应的,能匹配上的
     */
    public class Schema1 implements AbstractFactory {
    	public CPUApi createCPUApi() {
    		return new IntelCPU(1156);
    	}
    
    
    	public MainboardApi createMainboardApi() {
    		return new GAMainboard(1156);
    	}
    }

    6.4装机方案二

    package demo06.abstractfactory.example3;
    
    
    /**
     * 装机方案二:AMD的CPU + 微星的主板 这里创建CPU和主板对象的时候,是对应的,能匹配上的
     */
    public class Schema2 implements AbstractFactory {
    	public CPUApi createCPUApi() {
    		return new AMDCPU(939);
    	}
    
    
    	public MainboardApi createMainboardApi() {
    		return new MSIMainboard(939);
    	}
    }

    6.5装机工程师

    package demo06.abstractfactory.example3;
    
    
    /**
     * 装机工程师的类
     */
    public class ComputerEngineer {
    	/**
    	 * 定义组装机器需要的CPU
    	 */
    	private CPUApi cpu = null;
    	/**
    	 * 定义组装机器需要的主板
    	 */
    	private MainboardApi mainboard = null;
    
    
    	/**
    	 * 装机过程
    	 * 
    	 * @param schema
    	 *            客户选择的装机方案
    	 */
    	public void makeComputer(AbstractFactory schema) {
    		// 1:首先准备好装机所需要的配件
    		prepareHardwares(schema);
    		// 2:组装机器
    
    
    		// 3:测试机器
    
    
    		// 4:交付客户
    	}
    
    
    	/**
    	 * 准备装机所需要的配件
    	 * 
    	 * @param schema
    	 *            客户选择的装机方案
    	 */
    	private void prepareHardwares(AbstractFactory schema) {
    		// 这里要去准备CPU和主板的具体实现,为了示例简单,这里只准备这两个
    		// 可是,装机工程师并不知道如何去创建,怎么办呢?
    
    
    		// 使用抽象工厂来获取相应的接口对象
    		this.cpu = schema.createCPUApi();
    		this.mainboard = schema.createMainboardApi();
    
    
    		// 测试一下配件是否好用
    		this.cpu.calculate();
    		this.mainboard.installCPU();
    	}
    }

    6.6客户端使用

    package demo06.abstractfactory.example3;
    
    
    public class Client {
    	public static void main(String[] args) {
    		// 创建装机工程师对象
    		ComputerEngineer engineer = new ComputerEngineer();
    		// 客户选择并创建需要使用的装机方案对象
    		AbstractFactory schema = new Schema1();
    		// 告诉装机工程师自己选择的装机方案,让装机工程师组装电脑
    		engineer.makeComputer(schema);
    	}
    }

    7.抽象工厂模式讲解

    7.1抽象工厂和DAO

    DAO是数据访问对象,是J2EE中的一种标准的模式,是为了解决访问数据不同而产生的一种设计模式。这种设计模式简言之是:分层设计的思想。
    在实现DAO模式的时候,多用工厂的策略,最常用的就是抽象工厂模式,当然最好结合工厂方法模式。

    7.2抽象工厂的优缺点

    优点:分离接口和实现
    使得切换产品簇更加容易。
    缺点:不太容易扩展新的产品
    容易造成类层次复杂

    7.3抽象工厂模式的本质

    选择产品簇的实现

  • 相关阅读:
    instance of type of object.prototype.tostring 区别
    字符串属性及方法大总结
    数组属性及方法大总结
    在Vue中遇到的各种坑 及性能提升
    find、filter、map的区别
    react 的CDN 连接
    react开启一个项目 webpack版本出错
    react中的jsx详细理解
    Vue 在beaforeCreate时获取data中的数据
    vue点击时动态改变样式 ------- 最简单的方法
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3163123.html
Copyright © 2011-2022 走看看