设计模式——工厂模式
前言
传统模式创建的优缺点
- 优点是比较好理解,简单易操作。
- 缺点是违反了设计模式的 ocp 原则,即对扩展开放,对修改关闭。即当我们给类增加新功能的时候,尽量不修改代码,或者尽可能少修改代码
- 比如我们这时要新增加一个新的实现类,需要修改源代码
现有3个类,分别是Coffee、AmericanCoffee、LatteCoffee
- Coffee类
public class Coffee {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void addSugar(){
System.out.println("Coffee加糖");
}
public void addMilk(){
System.out.println("Coffee加奶");
}
}
- AmericanCoffee
public class AmericanCoffee extends Coffee {
@Override
public void addSugar(){
System.out.println("AmericanCoffee加糖");
}
@Override
public void addMilk(){
System.out.println("AmericanCoffee加奶");
}
}
- LatteCoffee
public class LatteCoffee extends Coffee {
@Override
public void addSugar(){
System.out.println("LatteCoffee加糖");
}
@Override
public void addMilk(){
System.out.println("LatteCoffee加奶");
}
}
1.简单工厂模式
简单工厂模式不是一个正式的设计模式,但它是工厂模式的基础。
它使用一个单独的工厂类来创建不同的对象,根据参数类型决定创建哪种类型的对象。
1.1 简单介绍
- 简单工厂模式是属于创建型模式,是工厂模式的一种。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式
- 简单工厂模式:定义了一个创建对象的类,由这个类来封装实例化对象的行为(代码)
- 在软件开发中,当我们会用到大量的创建某种、某类或者某批对象时,就会使用到工厂模式
1.2 代码实现
public class SimpleCoffeeFactory {
public Coffee createCoffee(String type){
Coffee coffee = null;
if ("american".equals(type)) {
return new AmericanCoffee();
} else if ("latte".equals(type)) {
return new LatteCoffee();
}
return coffee;
}
}
这样每次创建只需要根据type来判断就行了,而且如果你新增了一个子类(浓缩咖啡)也不用去修改父类的代码,只需要修改工厂的代码即可
public class SimpleCoffeeFactory {
public Coffee createCoffee(String type){
Coffee coffee = null;
if ("american".equals(type)) {
return new AmericanCoffee();
} else if ("latte".equals(type)) {
return new LatteCoffee();
} else if ("nongsuo".equals(type)){
return NongSuoCoffee();
}
return coffee;
}
}
1.3 优缺点
- 封装了创建对象的过程,可以通过参数直接获取对象。把对象的创建和业务逻辑层分开,这样以后就避免了修改客户代码,如果要实现新产品直接修改工厂类,而不需要在原代码中修改,这样就降低了客户代码修改的可能性,更加容易扩展。
- 增加新产品时还是需要修改工厂类的代码,违背了“开闭原则"
2.工厂方法模式
2.1 简单介绍
- 工厂方法模式设计方案:将实例化功能抽象成抽象方法,根据不同的类型实例化子类。
- 工厂方法模式:定义了一个创建对象的抽象方法,由子类决定要实例化的类。工厂方法模式将对象的实例
2.2 代码实现
- 需要一个咖啡工厂
public interface CoffeeFactory {
Coffee createCoffee();
}
- 美式咖啡工厂
public class AmericanCoffeeFactory implements CoffeeFactory {
public Coffee createCoffee() {
return new AmericanCoffee();
}
}
- 拿铁咖啡工厂
public class LatteCoffeeFactory implements CoffeeFactory {
public Coffee createCoffee() {
return new LatteCoffee();
}
}
同样,如果你需要添加一个浓缩咖啡,只需要创建一个浓缩咖啡工厂的实现类,来实现咖啡工厂,通过Java的多态来创建想要的咖啡对象
2.3 优缺点
- 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程;在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改满足开闭原则;
- 每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度。
3.抽象工厂模式
3.1 简单介绍
- 抽象工厂模式:定义了一个interface 用于创建相关或有依赖关系的对象簇,而无需指明具体的类
- 抽象工厂模式可以将简单工厂模式和工厂方法模式进行整合。
- 从设计层面看,抽象工厂模式就是对简单工厂模式的改进(或者称为进一步的抽象)。
- 将工厂抽象成两层,AbsFactory(抽象工厂)和 具体实现的工厂子类。程序员可以根据创建对象类型使用对应的工厂子类。这样将单个的简单工厂类变成了工厂簇,更利于代码的维护和扩展。
3.2 代码实现
现有需求添加甜品,那么咖啡工厂就不够用了,所以这个时候我们往上套一个工厂,既可以创建咖啡,又可以创建甜品
public interface DessertFactory {
Coffee createCoffee();
Dessert createDessert();
}
public class ItalyDessertFactory implements DessertFactory {
public Coffee createCoffee() {
return new LatteCoffee();
}
public Dessert createDessert() {
return new Tiramisu();
}
}
public class AmericanDessertFactory implements DessertFactory {
public Coffee createCoffee() {
return new AmericanCoffee();
}
public Dessert createDessert(){
return new MatchaMousse();
}
}
3.3 优缺点
- 当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象.
- 当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。
总结
工厂模式的意义
将实例化对象的代码提取出来,放到一个类中统一管理和维护,达到和主项目的依赖关系的解耦。从而提高项目的扩展和维护性。
- 三种工厂模式(简单工厂模式、工厂方法模式、抽象工厂模式)
- 设计模式的依赖抽象原则
- 创建对象实例时,不要直接 new 类,而是把这个new 类的动作放在一个工厂的方法中,并返回。有的书上说变量不要直接持有具体类的引用。
- 不要让类继承具体类,而是继承抽象类或者是实现interface(接口)
- 不要覆盖基类中已经实现的方法。