工厂模式
在平时编程中,构建对象最常用的方式是 new 一个对象。乍一看这种做法没什么不好,而实际上这也属于一种硬编码。每 new 一个对象,相当于调用者多知道了一个类,增加了类与类之间的联系,不利于程序的松耦合。其实构建过程可以被封装起来,工厂模式便是用于封装对象的设计模式。
简单工厂模式
/**
* @Author: mahy
* @Contact: [email protected]
* @Date: 2022-03-07 14:54
* @Description: 动物的实体类
*/
public class Animal {
public String sleep(){
return null;
}
}
/**
* @Author: mahy
* @Contact: [email protected]
* @Date: 2022-03-07 14:52
* @Description: 猫的实体类
*/
public class Cat extends Animal {
@Override
public String sleep(){
return "猫在睡觉";
}
}
/**
* @Author: mahy
* @Contact: [email protected]
* @Date: 2022-03-07 14:51
* @Description: 狗的实体类
*/
public class Dog extends Animal{
@Override
public String sleep(){
return "狗在睡觉";
}
}
/**
* @Author: mahy
* @Contact: [email protected]
* @Date: 2022-03-07 14:53
* @Description: 工厂类
*/
public class AnimalFactory {
public Animal create(String action){
switch (action){
case "猫": return new Cat();
case "狗": return new Dog();
default: throw new IllegalArgumentException("没有这种动物");
}
}
}
/**
* @Author: mahy
* @Contact: [email protected]
* @Date: 2022-03-07 14:02
* @Description: 测试简单工厂模式
*/
public class Test001 {
public static void main(String[] args) {
AnimalFactory factory = new AnimalFactory();
Animal cat = factory.create("猫");
Animal dog = factory.create("狗");
String catSleep = cat.sleep();
String dogSleep = dog.sleep();
System.out.println(catSleep); //猫在睡觉
System.out.println(dogSleep); //狗在睡觉
}
}
调用者完全不用关系猫跟狗中代码的变化,如果新增一种动物,调用者只需要根据名称调用即可,不用管它是怎么生成的,或者怎么生长的。
注:在 《设计模式》一书中,简单工厂模式被划分为工厂方法模式的一种特例,没有单独被列出来。
总而言之,简单工厂模式就是让一个工厂类承担构建所有对象的职责。调用者需要什么产品,让工厂生产出来即可。它的弊端也显而易见:
一是如果需要生产的产品过多,此模式会导致工厂类过于庞大,承担过多的职责,变成超级类。当苹果生产过程需要修改时,要来修改此工厂。梨子生产过程需要修改时,也要来修改此工厂。也就是说这个类不止一个引起修改的原因。违背了单一职责原则。
二是当要生产新的产品时,必须在工厂类中添加新的分支。而开闭原则告诉我们:类应该对修改封闭。我们希望在添加新功能时,只需增加新的类,而不是修改既有的类,所以这就违背了开闭原则。
工程方法模式
为了解决简单工厂模式的这两个弊端,工厂方法模式应运而生,它规定每个产品都有一个专属工厂。
实体类照样是上面的
/**
* @Author: mahy
* @Contact: [email protected]
* @Date: 2022-03-07 15:10
* @Description: 狗的工厂类方法
*/
public class DogFactory {
public Animal create(){
return new Dog();
}
}
/**
* @Author: mahy
* @Contact: [email protected]
* @Date: 2022-03-07 15:11
* @Description: 猫的工程类方法
*/
public class CatFactory {
public Animal create(){
return new Cat();
}
}
/**
* @Author: mahy
* @Contact: [email protected]
* @Date: 2022-03-07 14:02
* @Description: 测试工厂类方法模式
*/
public class Test001 {
public static void main(String[] args) {
DogFactory factory = new DogFactory();
Dog dog = (Dog) factory.create();
CatFactory factory1 = new CatFactory();
Cat cat = (Cat) factory1.create();
String dogSleep = dog.sleep();
String catSleep = cat.sleep();
System.out.println(dogSleep); //狗在睡觉
System.out.println(catSleep); //猫在睡觉
}
}
调用者无需知道狗或者猫的生产细节,当生产过程需要修改时也无需更改调用端。同时,工厂方法模式解决了简单工厂模式的两个弊端。
当生产的产品种类越来越多时,工厂类不会变成超级类。工厂类会越来越多,保持灵活。不会越来越大、变得臃肿。如果狗或者猫的生产过程需要修改时,只需修改狗工厂。猫的生产过程需要修改时,只需修改猫工厂。符合单一职责原则。
当需要生产新的产品时,无需更改既有的工厂,只需要添加新的工厂即可。保持了面向对象的可扩展性,符合开闭原则。