【设计模式(一)】创建型模式--工厂方法模式
创建型模式的主要关注点是“怎样创建对象?”,它的主要特点是“将对象的创建与使用分离”。这样可以降低系统的耦合度,使用者不需要关注对象的创建细节。
在了解工厂方法模式之前,有必要对“简单工厂”模式进⾏⼀定的了解,简单工厂模式是⼀种创建型设计模式,但并不属于23种设计模式之⼀,更多的是⼀种编程习惯。
简单工厂模式的核心思想是将产品的创建过程封装在⼀个工厂类中,把创建对象的流程集中在这个工厂类里面。
简单工厂包含如下角色:
- 抽象产品 :定义了产品的规范,描述了产品的主要特性和功能。
- 具体产品 :实现或者继承抽象产品的子类
- 具体工厂 :提供了创建产品的方法,调用者通过该方法来获取产品。
以咖啡店点咖啡为例,Coffee接口是抽象产品,AmericanCoffee和LatteCoffee是具体产品,SimpleCoffeeFactory是具体工厂。
简单工厂类简化了客户端(咖啡店CoffeeStore)操作,客户端可以调用工厂方法来获取具体产品,而无需直接与具体产品类交互,降低了耦合,但是有⼀个很⼤的问题就是不够灵活,如果需要添加新的产品,就需要修改工厂类的代码。
咖啡接口和具体咖啡产品代码
public interface Coffee {
void getName();
}
public class AmericanCoffee implements Coffee{
@Override
public void getName() {
System.out.println("我是美国咖啡");
}
}
public class LatteCoffee implements Coffee{
@Override
public void getName(){
System.out.println("我是拿铁咖啡");
}
}
工厂(此处使用静态工厂)和客服端代码
public class SimpleCoffeeFactory {
public static Coffee createCoffee(String type){
switch (type){
case "AmericanCoffee" -> {return new AmericanCoffee();}
case "LatteCoffee" -> {return new LatteCoffee();}
default ->{
System.out.println("没有这种咖啡");
return null;
}
}
}
}
public class CoffeeStore {
public Coffee orderCoffee(String type){
//客户端从工厂拿咖啡,而不是直接自己创建咖啡
Coffee coffee = SimpleCoffeeFactory.createCoffee(type);
if(coffee != null){
coffee.getName();
}
return coffee;
}
}
工厂方法模式
工厂方法模式也是⼀种创建型设计模式,简单工厂模式只有⼀个工厂类,负责创建所有产品,如果要添加新的产品,通常需要修改工厂类的代码。而工厂方法模式引入了抽象工厂和具体工厂的概念,每个具体工厂只负责创建⼀个具体产品,添加新的产品只需要添加新的工厂类而无需修改原来的代码,这样就使得产品的⽣产更加灵活,支持扩展,符合开闭原则。
工厂方法模式分为以下几个角色:
- 抽象工厂:一个接口,包含一个抽象的工厂方法(⽤于创建产品对象)。
- 具体工厂:实现抽象工厂接口,创建具体的产品。
- 抽象产品:定义产品的接口。
- 具体产品:实现抽象产品接口,是工厂创建的对象。
将上面咖啡例子改成工厂模式代码,咖啡接口和具体咖啡实现类不用变,只需提取一个抽象工厂接口,每种咖啡都有一个具体的工厂实现类负责生产咖啡,咖啡店指定具体咖啡实现类来生产不同咖啡。
public interface Factory {
Coffee creatCoffee();
}
public class AmericanCoffeeFactory implements Factory{
@Override
public Coffee creatCoffee() {
return new AmericanCoffee();
}
}
public class LatteCoffeeFactory implements Factory{
@Override
public Coffee creatCoffee() {
return new LatteCoffee();
}
}
public class CoffeeStore {
public Coffee orderCoffee(Factory factory){
Coffee coffee = factory.creatCoffee();
coffee.getName();
return coffee;
}
}
优点:
- 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程;
- 在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则;
缺点:
- 每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度。