设计模式 简单工厂 工厂 抽象工厂
1 简单工厂模式
1.1 定义
简单工厂模式又叫静态工厂模式,但不属于23种设计模式之一。
简单来说就是有一个类,提供一个创建方法createProduct,根据接收到的值决定实例化哪个类,但是这个简单工厂类能实例化的类必须都是同一个抽象类下的子类
1.2 实际应用场景
在JDK的类库中广泛使用了这个模式,比如DateFormat,可以看到根据传入的参数不同,返回不同DateFormat类的子类
1.3 手动实现
为了便于学习,代码都写在一个文件下
public class SimpleFactory {
/**
* 提供一个createProduct方法,根据传入的参数决定要创建哪个类的对象
* @param type
* @return
*/
public static Product createProduct(String type) {
if ("A".equals(type)) {
return new ProductA();
} else {
return new ProductB();
}
}
public static void main(String[] args) {
Product product = SimpleFactory.createProduct("A");
product.print();
}
}
/**
* 创建一个抽象类 声明一个抽象方法
*/
abstract class Product{
public abstract void print();
}
/**
* 创建抽象类的子类A 实现抽象方法
*/
class ProductA extends Product{
@Override
public void print() {
System.out.println("产品A创建了");
}
}
/**
* 创建抽象类的子类B 实现抽象方法
*/
class ProductB extends Product{
@Override
public void print() {
System.out.println("产品B创建了");
}
}
1.4 优缺点
- 拓展:开闭原则
程序对于拓展是开放的,对于修改是封闭的,核心观点:拓展优于修改
优点:实现了对象的创建和使用的分离,创建完全交给专门的工厂类负责,客户端程序员无需关心对象如何创建,只需要关心怎么使用
缺点:简单工厂模式不够灵活,每次新增产品类就要修改工厂类的判断逻辑,如果产品类很多,这个逻辑就会很复杂,同时修改工厂类违反了开闭原则
2 工厂模式
2.1 定义
简单来说就是只定义一个工厂类接口,再实现接口得到不同的子工厂类,让子工厂类分别负责不同的产品类的创建,而这些产品类依然属于同一个接口下不同的实现类
2.2 对比简单工厂模式
简单工厂模式
创建一个工厂类,每当新增一个产品类时就要修改工厂类
工厂模式
定义一个工厂接口,只给出工厂类要实现的方法,而不再负责创建对象,转而由工厂接口的各个实现类去创建对象,每当新增一个产品类时,只需要创建一个新的工厂类
2.3 实际应用场景
最常见的集合类Collection只是一个接口,对应着就是一个工厂接口,而具体的子类比如Arraylist,实现collection接口,就是一个实现了工厂接口的工厂类。
ArrayList能创建itr的实例,而itr是Iterator的实现类,因此整个过程就是一个工厂模式的运用。
类图如下
collection就是抽象工厂,具体工厂就是LinkedList,ArrayList,Iteratior就是抽象产品,具体产品就是ListItr和Itr,他们分别由LinkedList和ArrayList创建
2.4 手动实现
为了便于学习,将代码都放在一个文件下
public class FactoryPattern {
public static void main(String[] args) {
Factory factory = new ProductAFactory();
Product product = factory.create();
product.print();
}
}
/**
* 创建产品类接口
*/
interface Product{
void print();
}
/**
* 创建产品子类A并实现接口
*/
class ProductA implements Product{
@Override
public void print() {
System.out.println("产品A被创建了");
}
}
/**
* 创建产品子类B并实现接口
*/
class ProductB implements Product{
@Override
public void print() {
System.out.println("产品B被创建了");
}
}
/**
* 创建工厂接口
*/
interface Factory{
Product create();
}
/**
* 创建工厂子类A并生产产品子类A
*/
class ProductAFactory implements Factory{
@Override
public Product create() {
return new ProductA();
}
}
/**
* 创建工厂子类B并生产产品子类B
*/
class ProductBFactory implements Factory{
@Override
public Product create() {
return new ProductB();
}
}
2.5 优缺点
优点:解决了简单工厂模式违反开闭原则的问题
缺点:工厂模式的每一个子工厂类只能创建固定的某个产品类,每当新增产品类时,就得新增一个子工厂类
3 抽象工厂模式
3.1 定义
简单来说就是令工厂类和产品类原本一对一的关系变成了一对多,但是如果要扩展产品类,那么还是要修改工厂接口和各个子工厂类的代码,违反开闭原则
3.2 对比工厂模式
-
抽象工厂模式解决了工厂模式的工厂类和产品类一一对应的缺点,每个工厂类可以创建其他产品类,但是抽象工厂模式的扩展性和简单工厂模式一样差,会违反开闭原则。
-
工厂方法模式对具体产品可扩展,抽象工厂模式对具体产品族可扩展
-
抽象工厂模式只是工厂模式的一个扩展,如果只有一个产品类,那么抽象工厂模式就会退化成工厂模式
3.3 手动实现
为了便于学习,将代码都放在一个文件下
/**
* 抽象工厂
*/
interface AbstractFactory{
Phone createPhone(String param);
Mask createMask(String param);
}
/**
* 具体工厂 可以创建产品A和B 即工厂类和产品类实现了一对多
*/
class SuperFactory implements AbstractFactory{
@Override
public Phone createPhone(String param) {
if ("A".equals(param)) {
return new iphone();
}else{
return new huawei();
}
}
@Override
public Mask createMask(String param) {
if ("C".equals(param)){
return new N95();
}else {
return new normal();
}
}
}
/**
* 抽象产品A
*/
interface Phone{}
/**
* 具体产品A和B
*/
class iphone implements Phone{}
class huawei implements Phone{}
/**
* 抽象产品B
*/
interface Mask{}
/**
* 具体产品C和D
*/
class N95 implements Mask{}
class normal implements Mask{}