• 5、设计模式之工厂模式


    5.1 案例引入

     需求:设计一个披萨订购系统。
     设计一个抽象披萨类(Coffee),并定义其两个子类(奶酪披萨【CheessPizza】和水果披萨【FruitPizza】);再设计一个披萨店类(PizzaStore),披萨店具有点披萨的功能。
     类图如下:
    在这里插入图片描述
     代码如下:
    Pizza类:

    package d3_factory.t1_simple.before;
    /**
     * 披萨类 - 抽象
     * @author luxianghai
     *
     */
    public abstract class Pizza {
    	// 咖啡名
    	protected String name;
    	
    	// 准备工作
    	protected abstract void prepare();
    	
    	// 烘烤
    	protected void bake() {
    		System.out.println(name + " - 烘烤");
    	}
    	
    	protected void cut() {
    		System.out.println(name + " - 切割");
    	}
    	protected void box() {
    		System.out.println(name + " - 打包");
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    CheesePizza类

    package d3_factory.t1_simple.before;
    /**
     * 奶酪披萨
     * @author luxianghai
     *
     */
    public class CheesePizza extends Pizza {
    	
    	public CheesePizza() {
    		super.name = "奶酪披萨";
    	}
    	
    	@Override
    	protected void prepare() {
    		System.out.println(super.name);		
    		System.out.println("准备奶酪中...");		
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    FruitPizza类

    package d3_factory.t1_simple.before;
    /**
     * 水果披萨
     * @author luxianghai
     *
     */
    public class FruitPizza extends Pizza {
    
    	public FruitPizza() {
    		super.name = "水果披萨";
    	}
    	
    	@Override
    	protected void prepare() {
    		System.out.println(super.name);
    		System.out.println("准备水果中...");
    	}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    PizzaSotre类

    package d3_factory.t1_simple.before;
    
    import java.util.Scanner;
    
    /**
     * 披萨店
     * @author luxianghai
     *
     */
    public class PizzaStore {
    	
    	public PizzaStore() {
    		orderPizza();
    	}
    	
    	/**
    	 * 点披萨
    	 */
    	private void orderPizza() {
    		Pizza pizza = null;
    		String type = ""; // 披萨类型
    		do {
    			type = getType();
    			if ( "奶酪披萨".equals(type) ) {
    				pizza = new CheesePizza();
    			} else if ( "水果披萨".equals(type) ) {
    				pizza = new FruitPizza();
    			} else {
    				System.out.println("退出!!!");
    				break;
    			}
    			pizza.prepare();
    			pizza.bake();
    			pizza.cut();
    			pizza.box();
    		} while(true);
    	}
    	/**
    	 * 获取披萨类型
    	 * @return
    	 */
    	private String getType() {
    		System.out.println("输入披萨名:");
    		Scanner scan = new Scanner(System.in);
    		return scan.next();
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    测试

    package d3_factory.t1_simple.before;
    
    public class Client {
    
    	public static void main(String[] args) {
    		new PizzaStore();
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

     优缺点分析

    1. 优点是比较好理解,简单易操作。
    2. 缺点是违反了设计模式的ocp原则,即对扩展开放,对修改关闭。即当我们给类增加新功能的时候,尽量不修改代码,或者尽可能少修改代码.
    3. 比如我们这时要新增加一个Pizza的种类(ChickenPizza鸡肉披萨),我们需要在 PizzaStore的orderPizza方法中添加else if来进行判断

     改进思路分析:

    • 分析:修改代码可以接受,但是如果我们在其它的地方也有创建Pizza的代码,就意味着,也需要修改,而创建Pizza的代码,往往有多处。
    • 思路:把创建Pizza对象封装到一个类中,这样我们有新的Pizza种类时,只需要修改该类就可,其它有创建到Pizza对象的代码就不需要修改了 --> 简单工厂模式

    5.2简单工厂模式

    简单工厂不是一种设计模式,反而比较像是一种编程习惯。

    5.2.1 简单工厂模式结构

     简单工厂模式的结构:

    1. 抽象产品 :定义产品的规范,描述产品的主要特性和功能。
    2. 具体产品 :实现或者继承抽象产品的子类
    3. 具体工厂 :提供了创建产品的方法,调用者通过该方法来获取产品。

    5.2.2 实现

     使用简单工厂对 5.1小节 中的案例进行改进,我们只需对PizzaStore做修改(把创建对象的语句提取到工厂中),并创建一个简单工厂SimpleFactory类即可,代码如下:
    SimpleFactory.java

    package d3_factory.t1_simple.after1;
    /**
     * 简单工厂类
     * @author luxianghai
     *
     */
    public class SimpleFactory {
    	
    	public Pizza createPizza(String type) {
    		Pizza pizza = null;
    		if ( "奶酪披萨".equals(type) ) {
    			pizza = new CheesePizza();
    		} else if ( "水果披萨".equals(type) ) {
    			pizza = new FruitPizza();
    		}
    		return pizza;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    PizzaStore

    package d3_factory.t1_simple.after2;
    
    import java.util.Scanner;
    
    /**
     * 披萨店
     * @author luxianghai
     *
     */
    public class PizzaStore {
    	
    	public PizzaStore() {
    		orderPizza();
    	}
    	
    	/**
    	 * 点披萨
    	 */
    	private void orderPizza() {
    		String type = ""; // 披萨类型
    		do {
    			type = getType();
    			Pizza pizza = SimpleFactory.createPizza(type);
    			if(null != pizza) {
    				pizza.prepare();
    				pizza.bake();
    				pizza.cut();
    				pizza.box();
    			} else {
    				System.out.println("退出!!!");
    				break;
    			}
    		} while(true);
    	}
    	/**
    	 * 获取披萨类型
    	 * @return
    	 */
    	private String getType() {
    		String type = "";
    		Scanner scan = null;
    		try {
    			System.out.println("输入披萨名:");
    			scan = new Scanner(System.in);
    			type = scan.next();
    		} finally {
    			if ( null != scan ) {
    				scan.close();
    			}
    		}
    		return type;
    	}
    	
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

     此时如果我们新增一个鸡肉披萨,只需创建新类ChickenPizza,然后在SimpleFactory添加一个判断即可,就不需要修改客户端了,更容易扩展了:
    ChickenPizza

    package d3_factory.t1_simple.after2;
    /**
     * 鸡肉披萨
     * @author luxianghai
     *
     */
    public class ChickenPizza extends Pizza {
    	
    	public ChickenPizza() {
    		super.name = "鸡肉披萨";
    	}
    	@Override
    	protected void prepare() {
    		System.out.println("鸡肉披萨");
    		System.out.println("准备鸡肉中...");
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    SimpleFactory

    package d3_factory.t1_simple.after2;
    /**
     * 简单工厂类
     * @author luxianghai
     *
     */
    public class SimpleFactory {
    	
    	public static Pizza createPizza(String type) {
    		Pizza pizza = null;
    		if ( "奶酪披萨".equals(type) ) {
    			pizza = new CheesePizza();
    		} else if ( "水果披萨".equals(type) ) {
    			pizza = new FruitPizza();
    		} else if ( "鸡肉披萨".equals(type) ) {
    			pizza = new FruitPizza();
    		}
    		return pizza;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

     如此边添加了一个新的披萨种类

    5.2.3 优缺点分析

     优点:封装了创建对象的过程,可以通过参数直接获取对象。把对象的创建和业务逻辑层分开,这样以后就避免了修改客户代码,如果要实现新产品直接修改工厂类,而不需要在原代码中修改,这样就降低了客户代码修改的可能性,更加容易扩展。
     缺点:增加新产品时还是需要修改工厂类的代码,违背了“开闭原则”

    5.3 工厂方法模式

    定义一个用于创建对象的接口或抽象类,让子类决定实例化哪个产品类对象。工厂方法使一个产品类的实例化延迟到其工厂的子类。

    5.3.1 工厂方法模式结构

    工厂方法模式的主要角色:

    1. 抽象工厂(Abstract Factory):提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法来创建产品。
    2. 具体工厂(ConcreteFactory):主要是实现抽象工厂中的抽象方法,完成具体产品的创建。
    3. 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能。
    4. 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应。

    5.3.2 新需求

    披萨项目新的需求:客户在点披萨时,可以根据所在地点不同的披萨,比如 北京的水果pizza、北京的奶酪pizza 或者是伦敦的奶酪pizza、伦敦的水果pizza。

    5.3.3 思路

     思路1:使用简单工厂模式,创建不同的简单工厂类,比如BJPizzaSimpleFactory、LDPizzaSimpleFactory 等等.从当前这个案例来说,也是可以的,但是考虑到项目的规模,以及软件的可维护性、可扩展性并不是特别好
     思路2:使用工厂方法模式

    5.3.4 实现

     类图如下:
    在这里插入图片描述
     代码如下:
    抽象产品

    /**
     * 披萨类 - 抽象产品
     * @author luxianghai
     *
     */
    public abstract class Pizza {
    	// 咖啡名
    	protected String name;
    	
    	// 准备工作
    	public abstract void prepare();
    	
    	// 烘烤
    	public void bake() {	
    		System.out.println(name + " - 烘烤");
    	}
    	
    	public void cut() {
    		System.out.println(name + " - 切割");
    	}
    	public void box() {
    		System.out.println(name + " - 打包");
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    具体产品

    /**
     * 奶酪披萨 – 具体产品
     * @author luxianghai
     *
     */
    public class BJCheesePizza extends Pizza {
    	
    	public BJCheesePizza() {
    		super.name = "北京奶酪披萨";
    	}
    	
    	@Override
    	public void prepare() {
    		System.out.println(super.name);		
    		System.out.println("准备奶酪中...");		
    	}
    }
    
    /**
     * 水果披萨 – 具体产品
     * @author luxianghai
     *
     */
    public class BJFruitPizza extends Pizza {
    
    	public BJFruitPizza() {
    		super.name = "北京水果披萨";
    	}
    	
    	@Override
    	public void prepare() {
    		System.out.println(super.name);
    		System.out.println("准备水果中...");
    	}
    
    }
    
    /**
     * 奶酪披萨 – 具体产品
     * @author luxianghai
     *
     */
    public class LDCheesePizza extends Pizza {
    	
    	public LDCheesePizza() {
    		super.name = "伦敦奶酪披萨";
    	}
    	
    	@Override
    	public void prepare() {
    		System.out.println(super.name);		
    		System.out.println("准备奶酪中...");		
    	}
    }
    
    /**
     * 水果披萨  – 具体产品
     * @author luxianghai
     *
     */
    public class LDFruitPizza extends Pizza {
    
    	public LDFruitPizza() {
    		super.name = "伦敦水果披萨";
    	}
    	
    	@Override
    	public void prepare() {
    		System.out.println(super.name);
    		System.out.println("准备水果中...");
    	}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73

    抽象工厂

    import java.util.Scanner;
    
    import d3_factory.t2_factorymethod.pizza.*;
    
    /**
     * 抽象工厂
     * @author luxianghai
     *
     */
    public abstract class PizzaStore {
    	// 工厂子类需要实现的方法 - 常用创建具体产品
    	public abstract Pizza createPizza(String type);
    	
    	public PizzaStore() {
    		orderPizza();
    	}
    	
    	/**
    	 * 点披萨
    	 */
    	private void orderPizza() {
    		Pizza pizza = null;
    		String type = ""; // 披萨类型
    		do {
    			type = getType();
    			pizza = createPizza(type);
    			if ( null != pizza ) {
    				pizza.bake();
    				pizza.cut();
    				pizza.box();
    			} else {
    				break;
    			}
    		} while(true);
    	}
    	/**
    	 * 获取披萨类型
    	 * @return
    	 */
    	private String getType() {
    		System.out.println("输入披萨名:");
    		Scanner scan = new Scanner(System.in);
    		return scan.next();
    	}
    	
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    具体工厂

    /**
     * 伦敦披萨 - 具体工厂
     * @author luxianghai
     *
     */
    public class LDPizzaStore extends PizzaStore {
    
    	@Override
    	public Pizza createPizza(String type) {
    		Pizza pizza = null;
    		if ( "奶酪披萨".equals(type) ) {
    			pizza = new LDCheesePizza();
    		} else if ( "水果披萨".equals(type) ) {
    			pizza = new LDFruitPizza();
    		}
    		return pizza;
    	}
    
    }
    
    /**
     * BJ披萨 - 具体工厂
     * @author luxianghai
     *
     */
    public class BJPizzaStore extends PizzaStore {
    
    	@Override
    	public Pizza createPizza(String type) {
    		Pizza pizza = null;
    		if ( "奶酪披萨".equals(type) ) {
    			pizza = new BJCheesePizza();
    		} else if ( "水果披萨".equals(type) ) {
    			pizza = new BJFruitPizza();
    		}
    		return pizza;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    测试

    public class Client {
    
    	public static void main(String[] args) {
    		
    		//new BJPizzaStore();
    		new LDPizzaStore();
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    5.3.5 优缺点分析

     工厂方法就是对简单工厂在进行一次封装而已,由于多态性使得工厂方法仍然保持了简单工厂的优点。
     缺点:仍然违反开闭原则

    5.4 抽象工厂

    5.4.1 介绍

     抽象工厂模式:定义了一个interface用于创建相关或有依赖关系的对象簇,而无需指明具体的类。
     抽象工厂模式就是将工厂方法改进了一下,使其能够管理多个抽象产品。
     从设计层面看,抽象工厂模式就是对简单工厂模式的改进(或者称为进一步的抽象)。
     将工厂抽象成两层,AbsFactory(抽象工厂) 和 具体实现的工厂子类。程序员可以根据创建对象类型使用对应的工厂子类。这样将单个的简单工厂类变成了工厂簇,更利于代码的维护和扩展。

    5.4.2 结构

     抽象工厂模式的主要角色如下:

    1. 抽象工厂(Abstract Factory):提供了创建产品的接口,它包含多个创建产品的方法,可以创建多个不同等级的产品。
    2. 具体工厂(Concrete Factory):主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建。
    3. 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品。
    4. 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间是多对一的关系。

    5.4.3 实现

    我们只需要保留下工厂方法代码中的抽象产品和具体产品即可,其他的代码均删除,添加以下代码:
    抽象工厂

    /**
     * 抽象工厂
     * @author luxianghai
     *
     */
    public interface AbsFactory {
    	
    	Pizza createPizza(String type);
    	
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    具体工厂

    /**
     * BJ披萨 - 具体工厂
     * @author luxianghai
     *
     */
    public class BJPizzaStore implements AbsFactory {
    
    	@Override
    	public Pizza createPizza(String type) {
    		Pizza pizza = null;
    		if ( "奶酪披萨".equals(type) ) {
    			pizza = new BJCheesePizza();
    		} else if ( "水果披萨".equals(type) ) {
    			pizza = new BJFruitPizza();
    		}
    		return pizza;
    	}
    }
    
    /**
     * 伦敦披萨 - 具体工厂
     * @author luxianghai
     *
     */
    public class LDPizzaStore implements AbsFactory {
    
    	@Override
    	public Pizza createPizza(String type) {
    		Pizza pizza = null;
    		if ( "奶酪披萨".equals(type) ) {
    			pizza = new LDCheesePizza();
    		} else if ( "水果披萨".equals(type) ) {
    			pizza = new LDFruitPizza();
    		}
    		return pizza;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    业务类

    /**
     * 业务类
     * @author luxianghai
     *
     */
    public class PizzaStore {
    
    	private AbsFactory factory;
    	
    	public PizzaStore() {
    		
    	}
    	
    	public void setFactory(AbsFactory factory) {
    		this.factory = factory;
    		orderPizza();
    	}
    	
    	/**
    	 * 点披萨
    	 */
    	private void orderPizza() {
    		Pizza pizza = null;
    		String type = ""; // 披萨类型
    		do {
    			type = getType();
    			pizza = factory.createPizza(type);
    			if ( null != pizza ) {
    				pizza.prepare();
    				pizza.bake();
    				pizza.cut();
    				pizza.box();
    			} else {
    				break;
    			}
    		} while(true);
    	}
    	/**
    	 * 获取披萨类型
    	 * @return
    	 */
    	private String getType() {
    		System.out.println("输入披萨名:");
    		Scanner scan = new Scanner(System.in);
    		return scan.next();
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    测试

    public class Client {
    
    	public static void main(String[] args) {
    		
    		PizzaStore store = new PizzaStore();
    //		store.setFactory(new LDPizzaStore());
    		store.setFactory(new LDPizzaStore());
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

     此时的类图如下:在这里插入图片描述

    5.4.4 使用场景

    1. 当需要创建的对象是一系列相互关联或相互依赖的产品族时,如电器工厂中的电视机、洗衣机、空调等。
    2. 系统中有多个产品族,但每次只使用其中的某一族产品。如有人只喜欢穿某一个品牌的衣服和鞋。
    3. 系统中提供了产品的类库,且所有产品的接口相同,客户端不依赖产品实例的创建细节和内部结构。
    4. 如:输入法换皮肤,一整套一起换。生成不同操作系统的程序。

    5.5 工厂+配置文件实现解耦

     简单工厂+配置文件解除耦合
    可以通过工厂模式+配置文件的方式解除工厂对象和产品对象的耦合。在工厂类中加载配置文件中的全类名,并创建对象进行存储,客户端如果需要对象,直接进行获取即可。
    第一步:创建配置文件
    resources/bean.properties 文件内容

    ChickenPizza=d3_factory.t4_config_factory.ChickenPizza
    FruitPizza=d3_factory.t4_config_factory.FruitPizza
    
    • 1
    • 2

    第二步:创建简单工厂

    package d3_factory.t4_config_factory;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.HashMap;
    import java.util.Properties;
    import java.util.Set;
    
    public class SimpleFactory {
    	
    	// 加载配置文件 - 获取配置文件中配置的全类名,通过反射技术来创建对象
    	// 1.定义容器来存储Pizza对象
    	private static HashMap<String, Pizza> map ;
    	
    	static {
    		map = new HashMap<String, Pizza>();
    		// 1.创建Properties对象
    		Properties properties = new Properties();
    		// 2.读取配置文件
    		InputStream is = SimpleFactory.class.getClassLoader().getResourceAsStream("bean.properties");
    		try {
    			// 3.加载配置文件
    			properties.load(is);
    			// 获取 properties 中所有的键的 Set 集合
    			Set<Object> keys =  properties.keySet();
    			for ( Object key: keys ) {
    				// 获取键对应的值
    				String className = properties.getProperty((String)key);
    				// 通过反射技术根据全类名创建对象
    				Class clazz = Class.forName(className);
    				Pizza pizza = (Pizza)clazz.newInstance();
    				map.put((String)key, pizza);
    			}
    			
    		} catch (Exception e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		
    	}
    	
    	/**
    	 * 根据名称获取对象
    	 * @param name
    	 * @return
    	 */
    	public static Pizza createPizza(String name) {
    		return map.get(name);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    相关文章索引

    设计模式概述
    UML类图
    软件设计原则
    单例设计模式


    后记

    我水平有限,错误难免,还望各位加以指正。

    本文内容到此结束,感谢您的阅读!!!如果内容对你有帮助的话,记得给我三连丫(点赞、收藏、关注)

  • 相关阅读:
    音视频质检及画质评估——为QoS & QoE 指标保驾护航
    Java容器(arraylist+vector源码+stack)
    数据库系统执行模型
    微机原理:汇编语言语句类型与格式
    Day07 狂神说Java-MySQL>P40-P45
    求矩阵的行列式和逆矩阵 det()和inv()
    C# this的五种用法
    Spring Boot跨域处理
    Java加密算法有几种?
    充气膜结构的应用领域
  • 原文地址:https://blog.csdn.net/weixin_43113381/article/details/128013378