工厂模式
代码仓库:https://gitee.com/jerry_top/wm_design_patterns.git
1、普通写法
类图
案例
package top.jerrymo.pattern.factory.before;
public abstract class Fruit {
abstract String getName();
void wash(){
System.out.println("洗水果");
}
void cut(){
System.out.println("切水果");
}
}
public class AppleFruit extends Fruit {
@Override
String getName() {
return "苹果";
}
}
public class BananaFruit extends Fruit {
@Override
String getName() {
return "香蕉";
}
}
public class FruitShop {
// 根据类型判断生成对应的水果
public Fruit create(String type){
Fruit fruit = null;
switch (FruitTypeEnum.getInstance(type)){
case BANANA:
fruit = new BananaFruit();
break;
case APPLE:
fruit = new AppleFruit();
break;
default:
fruit = new Fruit() {
@Override
String getName() {
return "水果无法识别";
}
};
}
System.out.println(fruit.getName());
return fruit;
}
}
public enum FruitTypeEnum {
APPLE("apple", "苹果"),
BANANA("banana", "香蕉"),
UNDEFINE("undefine", "无法识别"),
;
...
...
}
/**
* @Auther: jerry
* @Date: 2021-07-03 16:27
* @Description: 问题:FruitShop 与具体的创建水果类耦合,假如我们需要更换对象,
* 则所有new对象的地方都要修改一遍,不符合开闭原则
* 改进:使用工厂来生成对象,只和工厂类对接,彻底解耦对象,
* 如果对象发生改变也只修改工厂类,具体的使用方无需修改(simple_factory)
*/
public class Client {
public static void main(String[] args) {
FruitShop fruitShop = new FruitShop();
Fruit fruit = fruitShop.create(FruitTypeEnum.APPLE.getType());
fruit.wash();
fruit.cut();
}
}
输出:
苹果
洗水果
切水果
总结
- 问题:FruitShop 与具体的创建水果类耦合,假如我们需要更换对象,则所有new对象的地方都要修改一遍,不符合开闭原则
- 改进:使用工厂类来生成对象,只和工厂类对接,彻底解耦对象, 如果对象发生改变也只修改工厂类,具体的使用方无需修改
2、简单工厂模式
定义
简单工厂模式(Simple Factory Pattern):又称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。在简单工厂模式中,可以根据参数的不同返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
结构
简单工厂包含如下角色:
- 抽象产品 :定义了产品的规范,描述了产品的主要特性和功能。(Fruit)
- 具体产品 :实现或者继承抽象产品的子类。(BananaFruit,AppleFruit)
- 具体工厂 :提供了创建产品的方法,调用者通过该方法来获取产品。(SimpleFruitFactory)
类图
案例
package top.jerrymo.pattern.factory.simple_factory;
public abstract class Fruit {
abstract String getName();
void wash(){
System.out.println("洗水果");
}
void cut(){
System.out.println("切水果");
}
}
public class AppleFruit extends Fruit {
@Override
String getName() {
return "苹果";
}
}
public class BananaFruit extends Fruit {
@Override
String getName() {
return "香蕉";
}
}
public class SimpleFruitFactory {
public Fruit create(String type){
Fruit fruit = null;
switch (FruitTypeEnum.getInstance(type)){
case BANANA:
fruit = new BananaFruit();
break;
case APPLE:
fruit = new AppleFruit();
break;
default:
fruit = new Fruit() {
@Override
String getName() {
return "水果无法识别";
}
};
}
System.out.println(fruit.getName());
return fruit;
}
}
public class FruitShop {
public Fruit create(String type){
SimpleFruitFactory factory = new SimpleFruitFactory();
Fruit fruit = factory.create(type);
return fruit;
}
}
/**
* @Auther: jerry
* @Date: 2021-07-03 16:27
* @Description: 优点:封装了创建对象的过程,可以通过参数直接获取对象。把对象的创建和业务逻辑层分开,
* 这样以后就避免了修改客户代码,如果要实现新产品直接修改工厂类,而不需要在原代码中修改,
* 这样就降低了客户代码修改的可能性,更加容易扩展。
* 缺点:添加了新的耦合,有新的水果时还是需要修改工厂类,违背了"开闭原则"。
*/
public class Client {
public static void main(String[] args) {
FruitShop fruitShop = new FruitShop();
Fruit fruit = fruitShop.create(FruitTypeEnum.BANANA.getType());
// fruit.wash();
fruit.cut();
}
}
输出:
香蕉
切水果
总结
- 优点:封装了创建对象的过程,可以通过参数直接获取对象。把对象的创建和业务逻辑层分开,这样以后就避免了修改客户(FruitShop)代码,如果要实现新产品直接修改工厂类,而不需要在原代码中修改,这样就降低了客户代码修改的可能性,更加容易扩展。
- 缺点:添加了新的耦合,有新的水果时还是需要修改工厂类,违背了"开闭原则"。
NEXT
工厂方法模式针对该缺点做了改进。读书百遍,其义自见。我是二十三月,下次见。