Update 工厂模式.md

master
Omooo 4 years ago
parent 6e7b4b9709
commit 7164e09415
  1. 163
      blogs/DesignMode/工厂模式.md

@ -10,6 +10,7 @@
- 简单工厂模式 - 简单工厂模式
- 工厂方法模式 - 工厂方法模式
- 抽象工厂模式 - 抽象工厂模式
4. 应用
#### 思维导图 #### 思维导图
@ -23,102 +24,138 @@
##### 简单工厂模式 ##### 简单工厂模式
我们写一个试图解析文件的例子。
```java ```java
//定义抽象产品类 public interface IFileParse {
public abstract class Product { String parse();
public abstract void method();
} }
```
```java public class JsonFileParse implements IFileParse {
//定义具体产品
public class ProductA extends Product {
@Override @Override
public void method() { public String parse() {
System.out.println("产品A"); return "Json";
} }
} }
public class ProductB extends Product {
public class XmlFileParse implements IFileParse {
@Override @Override
public void method() { public String parse() {
System.out.println("产品B"); return "Xml";
} }
} }
```
```java public class FileParseFactory {
//定义一个工厂用来生产产品
public class Factory { public IFileParse createFileParse(String name) {
public static Product createProduct(String type) { if ("xml".equals(name)) {
switch (type) { return new XmlFileParse();
case "A": } else if ("json".equals(name)) {
return new ProductA(); return new JsonFileParse();
case "B":
return new ProductB();
default:
return null;
} }
return null;
} }
} }
```
```java public class Resources {
//客户端根据传入的参数生成不同的产品
public class Client { public String parse(String name) {
public static void main(String[] args) { IFileParse fileParse = new FileParseFactory().createFileParse(name);
ProductA productA = (ProductA) Factory.createProduct("A"); if (fileParse != null) {
if (productA != null) { return fileParse.parse();
productA.method();
} else {
System.out.println("不存在产品A");
} }
throw new InvalidParameterException();
} }
} }
``` ```
这种写法很简单,但是问题也是显而易见的,每当增加新产品时就得改代码,违反了开闭原则。 这个就是一个简单工厂方法的写法,不过呢,每次调用 createFileParse 都会创建一个新的 FileParse 类。实际上,如果 FileParse 可以复用,为了节省内存和对象创建的时间,我们可以把 FileParse 缓存起来。
##### 工厂方法模式
将具体产品的创建延迟到具体工厂中完成,即由子类来决定应该实例化哪一个类。 具体写法就是:
```java ```java
//定义一个抽象工厂类 public class FileParseFactory {
public abstract class Factory {
public abstract Product createProduct();
}
```
```java private static HashMap<String, IFileParse> hashMap = new HashMap<>(4);
//具体的工厂,生产不同的产品
public class FactoryA extends Factory { static {
@Override hashMap.put("xml", new XmlFileParse());
public Product createProduct() { hashMap.put("json", new JsonFileParse());
return new ProductA();
} }
}
public class FactoryB extends Factory { public IFileParse createFileParse(String name) {
@Override return hashMap.get(name);
public Product createProduct() {
return new ProductB();
} }
} }
``` ```
##### 工厂方法模式
```java ```java
//用户决定要生产哪个产品 public class FileParseFactory {
public class Client {
public static void main(String[] args) { public interface IFileParseFactory {
Factory factory = new FactoryA();
ProductA productA = (ProductA) factory.createProduct(); IFileParse createFileParse();
productA.method(); }
new FactoryB().createProduct().method(); public class XmlFileParseFactory implements IFileParseFactory {
@Override
public IFileParse createFileParse() {
return new XmlFileParse();
}
}
public class JsonFileParseFactory implements IFileParseFactory {
@Override
public IFileParse createFileParse() {
return new JsonFileParse();
}
}
public IFileParse createFileParse(String name) {
if (name.equals("xml")) {
return new XmlFileParseFactory().createFileParse();
} else if (name.equals("json")) {
return new JsonFileParseFactory().createFileParse();
}
return null;
} }
} }
``` ```
缺点也是显而易见的,一个工厂只能生产一种产品,而且每一个产品都必须对应一个工厂,系统类成对增加,在一定程度上增加了系统的复杂度。 就是为每个 FileParse 在创建一个对应的 Factory,但是用到它时仅仅只是 new 创建了一个对象而已,这样写反而增加了复杂性,而且需要创建诸多的 Factory 类。在这个设计场景中,其实完全没有必要,简单工厂模式简单好用,比工厂方法更加适用。
那么时候该用工厂方法模式,而非简单工厂模式呢?
当对象的创建逻辑比较复杂,而不是简单的 new 一下就可以,而是要组合其他类对象,做各种初始化操作的时候,我们推荐使用工厂方法模式,将复杂的创建逻辑拆分到多个工厂类中,让每个工厂类都不至于过于复杂。而使用简单工厂模式,将所有的创建逻辑都放到一个工厂类中,会导致这个工厂类变得很复杂。
##### 抽象工厂模式 ##### 抽象工厂模式
抽象工厂模式的应用场景比较特殊,没有前两种常用,所以不作为重点,简单了解一下就行了。
#### 应用
在 Android 中,BitampFactory 用到了简单工厂模式,因为会根据的不同类型去创建 Bitmap。
```java
public class BitmapFactory {
public static Bitmap decodeFile(String pathName, Options opts) {
//...
}
public static Bitmap decodeResource() {
//...
}
public static Bitmap decodeByteArray() {
//...
}
}
```

Loading…
Cancel
Save