设计模式5-工厂模式(简单工厂、工厂方法、抽象工厂)

120 阅读4分钟

1.场景问题解决

1.1 场景描述

披萨商店,可以生产各种披萨.

2.用设计模式改进

2.1 简单工厂

2.1.1 概述思路

将变化的会有if else判断的相关模块,单独提到一个专门处理的类中(简单工厂).
简单工厂模式: 定义了一个创建对象的类,由这个类来封装实例化对象的行为

2.1.2 代码示例

  • abstract class Pizza (Pizza抽象类)
public abstract class Pizza {
	protected String name;
	
	public abstract void prepare();
	public void bake()
	{
		System.out.println(name+" baking;");
	}
	public void cut()
	{
		System.out.println(name+" cutting;");
	}
	public void box()
	{
		System.out.println(name+" boxing;");
	}
	public void setname(String name)
	{
		this.name=name;
	}
}

  • APizza,BPizza,CPizza (pizza实体类)
public class APizza extends Pizza {

	@Override
	public void prepare() {
		super.setname("APizza");
		System.out.println(name+" preparing;");
	}

}


public class BPizza extends Pizza {

	@Override
	public void prepare() {
		super.setname("BPizza");
		System.out.println(name+" preparing;");
	}
}



public class CPizza extends Pizza {
	@Override
	public void prepare() {
		super.setname("CPizza");
		System.out.println(name+" preparing;");
	}
}

  • SimplePizzaFactory
public class SimplePizzaFactory {
	public Pizza CreatePizza(String ordertype) {
		Pizza pizza = null;
		if (ordertype.equals("A")) {
			pizza = new APizza();
		} else if (ordertype.equals("B")) {
			pizza = new BPizza();
		} else if (ordertype.equals("C")) {
			pizza = new CPizza();
		}
		return pizza;
	}
}
  • TestOrderPizza测试类
public class TestOrderPizza {
	public static void main(String[] args) {
		SimplePizzaFactory mSimplePizzaFactory =   new SimplePizzaFactory();
		Pizza	pizza = mSimplePizzaFactory.CreatePizza("A");
		if (pizza != null) {
			pizza.prepare();
			pizza.bake();
			pizza.cut();
			pizza.box();
		}
		System.out.println(pizza);
	}
}

  • 运行结果
APizza preparing;
APizza baking;
APizza cutting;
APizza boxing;
*.pizza.APizza@6b884d57

2.2 工厂方法模式

2.2.1 需求变动带来问题

pizza生意好,将在各地开分店.
每个分店的工厂不一样了.

2.2.2 概述和思路

工厂方法模式:定义了一个创建对象的抽象方法,由子类决定要实例化的类。 工厂方法模式将对象的实例化推迟到子类

2.2.3 示例

  • Pizza,LDAPizza,LDBPizza,NYAPizza,NYBPizza
public abstract class Pizza {
	protected String name;
	
	public abstract void prepare();
	public void bake()
	{
		System.out.println(name+" baking;");
	}
	public void cut()
	{
		System.out.println(name+" cutting;");
	}
	public void box()
	{
		System.out.println(name+" boxing;");
	}
	public void setname(String name)
	{
		this.name=name;
	}
}


public class LDAPizza extends Pizza {
	@Override
	public void prepare() {
		super.setname("LDAPizza");
		System.out.println(name+" preparing;");
	}
}


public class LDBPizza extends Pizza {
	@Override
	public void prepare() {
		super.setname("LDBPizza");
		System.out.println(name+" preparing;");
	}
}


public class NYAPizza extends Pizza {
	@Override
	public void prepare() {
		super.setname("NYAPizza");
		System.out.println(name+" preparing;");
	}
}


public class NYBPizza extends Pizza {
	@Override
	public void prepare() {
		super.setname("NYBPizza");
		System.out.println(name+" preparing;");
	}
}


  • OrderPizza,LDOrderPizza,NYOrderPizza
public abstract class OrderPizza {
	public OrderPizza(){};
	public OrderPizza(String ordertype) {
		Pizza pizza = null;
		do {
			pizza = createPizza(ordertype);
			pizza.prepare();
			pizza.bake();
			pizza.cut();
			pizza.box();
		} while (true);
	}
	abstract Pizza createPizza(String ordertype);
}


public class LDOrderPizza extends OrderPizza {
	@Override
	Pizza createPizza(String ordertype) {
		Pizza pizza = null;

		if (ordertype.equals("A")) {
			pizza = new LDAPizza();
		} else if (ordertype.equals("B")) {
			pizza = new LDBPizza();
		}
		return pizza;
	}
}


public class NYOrderPizza extends OrderPizza {
	@Override
	Pizza createPizza(String ordertype) {
		Pizza pizza = null;

		if (ordertype.equals("A")) {
			pizza = new NYAPizza();
		} else if (ordertype.equals("B")) {
			pizza = new NYBPizza();
		}
		return pizza;
	}
}

  • 测试类TestPizzaStroe
public class TestPizzaStroe {
	public static void main(String[] args) {
		OrderPizza mOrderPizza = new NYOrderPizza();
		Pizza p1 = mOrderPizza.createPizza("A");
		System.out.println("p1->"+p1);
		OrderPizza mOrderPizza2 = new LDOrderPizza();
		Pizza p2 = mOrderPizza2.createPizza("B");
		System.out.println("p2->"+p2);
	}
}

  • 运行结果
p1->*.pizza.NYAPizza@6b884d57
p2->*.pizza.LDBPizza@38af3868

2.3.4 注意点

  • Pizza为抽象类,固定的为非抽象,可变的为抽象
    • LDA,LDB,NYA,NYB都继承抽象类Pizza
  • OrderPizza 为抽象类,抽象类OrderPizza中的createPizza为抽象方法. 真正的创建Pizza交给具体的实现类来处理.
    • LDOrderPizza和NYOrderPizza继承(extends) OrderPizza,实现createPizza,来生成各自的Pizza.

2.3 抽象工厂模式

2.4 抽象工程

2.4.1 分析

在工厂方法中,是将方法相关的抽象出来,那可以更深入点将工厂抽象出来.

2.4.2 示例

  • AbsFactory,LDFactory,NYFactory
public interface AbsFactory {
	public Pizza CreatePizza(String ordertype) ;
}


public class LDFactory implements AbsFactory {
	@Override
	public Pizza CreatePizza(String ordertype) {
		Pizza pizza = null;
		if (ordertype.equals("A")) {
			pizza = new LDAPizza();
		} else if (ordertype.equals("B")) {
			pizza = new LDBPizza();
		}
		return pizza;
	}
}



public class NYFactory implements AbsFactory {
	@Override
	public Pizza CreatePizza(String ordertype) {
		Pizza pizza = null;
		if (ordertype.equals("A")) {
			pizza = new NYAPizza();
		} else if (ordertype.equals("B")) {
			pizza = new NYBPizza();
		}
		return pizza;
	}
}

  • TestOrderPizza

public class TestOrderPizza {
	AbsFactory mFactory;
	Pizza pizza ;
	public TestOrderPizza(AbsFactory mFactory, String ordertype) {
		this.pizza = setFactoryAndOrder(mFactory,ordertype);
	}

	public Pizza setFactoryAndOrder(AbsFactory mFactory,String ordertype) {
		Pizza pizza = null;
		this.mFactory = mFactory;
		pizza = mFactory.CreatePizza(ordertype);
		if (pizza != null) {
			pizza.prepare();
			pizza.bake();
			pizza.cut();
			pizza.box();
		}
		return pizza;
	}

	public static void main(String[] args) {
		TestOrderPizza mOrderPizza=new TestOrderPizza(new LDFactory(),"A");
		System.out.println("mOrderPizza.getPizza()->"+mOrderPizza.getPizza());
	}

	public Pizza getPizza() {
		return pizza;
	}

	public void setPizza(Pizza pizza) {
		this.pizza = pizza;
	}
}

  • 运行结果
LDAPizza preparing;
LDAPizza baking;
LDAPizza cutting;
LDAPizza boxing;
mOrderPizza.getPizza()->*.pizza.LDAPizza@6b884d57

2.4.3 注意点

工厂都是抽象的,可以设置工厂

3.设计模式总结

3.1 定义

简单工厂模式:定义了一个创建对象的类,由这个类来封装实例化对象的行为.

  • 依赖抽象原则
    • 变量不要持有具体类的引用
    • 不要让类继承自具体类,要继承自抽象类或接口
    • 不要覆盖基类中已实现的方法

3.2 分析思路

3.2.1 引出工厂模式

分析项目中的变化部分和不变化部分,发现方法和执行不怎么变,而实例化部分改变,依赖性太强,那么就引出了对实例化部分进行改造,引出工厂模式.
--> 把项目中的实例化过程提取出来,将依赖关系进行解耦. 更好的扩展性,维护性.

3.2.2 工厂模式渐进

三种工程模式有一个循序渐进的过程:
对产生产品时直接判断(if else)[独立成工厂封装起来] (简单工厂)
---->对产生产品的方法进行抽象[接口类和实现类] (工厂方法)
---->对工厂进行抽象(抽象工厂)

4. 设计模式使用场景及注意

5.参考文章

内容总计于HeadFirst设计模式及相关视频