设计模式--------工厂模式
介绍工厂模式的四大问题
- 现在的写法有什么问题吗?
- 为什么要用工厂模式?
- 什么是工厂模式?
- 工厂模式有什么好处?
工厂模式细分
- 简单工厂模式
- 工厂方法模式
- 抽象工厂模式
采用一个案例来说明问题
- 现有一个披萨店,需要根据不同的需求制作披萨
常规思路
- 创建一个抽象Pizza类,其中有一系列制作步骤方法,不同种类的Pizza继承此类
- 创建一个PizzaStore类
- orderPizza(String type) : 根据传入的type制作不同种类的Pizza
public Pizza OrderPizza(String type) {
Pizza pizza = null;
if (type.equals("apple")) {
pizza = new ApplePizza();
} else if (type.equals("banana")) {
pizza = new BananaPizza();
}
pizza.cut();
pizza.pack();
return pizza;
}
现在的写法有什么问题吗?
- 每当有新的种类Pizza,就会修改当前的代码
- 应该将变化的和不变化的分来封装起来
简单工厂模式
- 创建一个工厂类,单独对创建Pizza进行处理,以达到每次新增只需修改工厂类就可以
Pizza抽象类
public abstract class Pizza {
public void cut() {
System.out.println("正在切Pizza...");
}
public void pack() {
System.out.println("正在打包Pizza...");
}
}
Pizza工厂类
public class PizzaFactory {
public Pizza createPizza(String type) {
Pizza pizza = null;
if (type.equals("apple")) {
pizza = new ApplePizza();
} else if (type.equals("banana")) {
pizza = new BananaPizza();
}
return pizza;
}
}
Pizza商店类
public class PizzaStore {
private PizzaFactory pizzaFactory;
public PizzaStore(PizzaFactory pizzaFactory) {
this.pizzaFactory = pizzaFactory;
}
public Pizza orderPizza(String type) {
Pizza pizza = pizzaFactory.createPizza(type);
pizza.cut();
pizza.pack();
return pizza;
}
}
Main
public class Main {
public static void main(String[] args) {
PizzaFactory pizzaFactory = new PizzaFactory();
PizzaStore pizzaStore = new PizzaStore(pizzaFactory);
pizzaStore.orderPizza("apple");
}
}
简单工厂模式好处和缺点?
- 简单工厂模式把Pizza中会变化的部分提取了出来,以致以后的新款式的增加不会影响到此类
- 便于出现类名更改,导致成千上万的类名要改变,只需改工厂中创建的那一处就可以
- 缺点在于每增加一个类都需要更改工厂类,不符合开闭原则
使用工厂方法模式进行改造(为了便于理解,把一些没用的去除了)
- 使用工厂方法模式将类的创建转移到了子类中
- 将具体要创建的类通过一个抽象方法由子类实现
Pizza
public abstract class Pizza {
public abstract void show();
}
ApplePizza
public class ApplePizza extends Pizza {
@Override
public void show() {
System.out.print("Apple");
}
}
PizzaFactory
public abstract class PizzaFactory {
public abstract Pizza createPizza();
}
ApplePizzaFactory
public class ApplePizzaFactory extends PizzaFactory {
@Override
public Pizza createPizza() {
return new ApplePizza();
}
}
Main
public class Main {
public static void main(String[] args) {
PizzaFactory factory = new ApplePizzaFactory();
Pizza pizza = factory.createPizza();
pizza.show();
}
}
工厂方法和简单工厂的区别(个人观点)
- 简单工厂不符合开闭原则,工厂方法符合开闭原则
- 简单工厂给人一种这个工厂全世界只有一家,它什么都能生产(这就导致每有一个新的就要加一个)
- 工厂方法给人一种有多家工厂,每个工厂只生产特有的一样或者多样产品(这就使每有一个新的就需要一个新的工厂),你要生产啥就实例化那个工厂以创建产品
- 工厂方法模式会有很多的类(缺点)
工厂方式的疑惑?
- 你说简单工厂的方式是为了不new一个对象,为了总的管理new,为了类改变而导致要改变多个new的地方,好,可以理解!
- 那么工厂方式不是又用了new的方式吗,同样是为了new一个Pizza,为什么不直接new,而要转来转去,还创建一个工厂
- 解答: 为了创建复杂对象,为了拓展性,简单对象只要new的就不要用工厂方式了
抽象工厂
- 抽象工厂:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类
各个模式使用场景(个人意见)
- 简单工厂模式: 因为只有一个工厂,而且是根据type进行创建的,所以只要不怕麻烦,可以让所有的具体产品类都由它生产,虽然这样是违反开闭原则的
- 工厂模式: 说是解决了开闭原则的模式,细想一下,也只是对于同类产品的更新迭代适用,例如要生产鼠标,那么会有多个品牌的鼠标,每一个工厂对应一个品牌的鼠标,通过具体实例化某一个品牌的工厂来生产我们所需的产品,而不是和简单工厂一样传入xx牌鼠标的type来实例化,但是要生产一个键盘的话,那不是要在工厂抽象类中再创建一个createKeyboard方法吗,然后xx牌工厂继承它,实现自己牌子的键盘,违反了开闭原则,而这样的方式又不叫工厂模式了,也就是下面的模式
- 抽象工厂模式:就是将一个工厂的多个产品一起作为一系列接口,可以这么说,抽象工厂模式用于拓展不同种类的产品,工厂模式用来拓展同类产品,拓展不同类产品同样会违反开闭原则(如果是生产流水线的工厂的话就不会违反开闭原则,因为流程一般是不变的,可以说抽象工厂就是为了这种模式产生的?)
- 其实选择什么模式就是根据你要做的东西的规模来决定
- 简单工厂:要是你是个小卖部,啥都买,那你就用简单工厂,因为同类东西你不一定有多样,何必复杂化呢
- 工厂模式:只生产某一样东西,多个工厂可以理解为多个品牌的区分,也可以理解为连锁店,多个地区的区分等等,这样同时满足了开闭原则
- 抽象工厂模式:大工厂,每个工厂有多个产品可以生产,也可以是每个工厂都是生产一个产品的流水线工程,简单的可以分为二类,一是一个工厂就是一个大公司,每个公司生产多个不同产品;二是一个工厂是一个公司某个地区的一个工厂,然后根据不同的地区产品有所变化,产品可以是一系列流水线工程或者是很多产品