|  |  |  | @ -10,6 +10,7 @@ | 
			
		
	
		
			
				
					|  |  |  |  |    - 简单工厂模式  | 
			
		
	
		
			
				
					|  |  |  |  |    - 工厂方法模式 | 
			
		
	
		
			
				
					|  |  |  |  |    - 抽象工厂模式 | 
			
		
	
		
			
				
					|  |  |  |  | 4. 应用 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | #### 思维导图 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -23,102 +24,138 @@ | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | ##### 简单工厂模式 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 我们写一个试图解析文件的例子。 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | ```java | 
			
		
	
		
			
				
					|  |  |  |  | //定义抽象产品类 | 
			
		
	
		
			
				
					|  |  |  |  | public abstract class Product { | 
			
		
	
		
			
				
					|  |  |  |  |     public abstract void method(); | 
			
		
	
		
			
				
					|  |  |  |  | public interface IFileParse { | 
			
		
	
		
			
				
					|  |  |  |  |     String parse(); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | ``` | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | ```java | 
			
		
	
		
			
				
					|  |  |  |  | //定义具体产品 | 
			
		
	
		
			
				
					|  |  |  |  | public class ProductA extends Product { | 
			
		
	
		
			
				
					|  |  |  |  | public class JsonFileParse implements IFileParse { | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     @Override | 
			
		
	
		
			
				
					|  |  |  |  |     public void method() { | 
			
		
	
		
			
				
					|  |  |  |  |         System.out.println("产品A"); | 
			
		
	
		
			
				
					|  |  |  |  |     public String parse() { | 
			
		
	
		
			
				
					|  |  |  |  |         return "Json"; | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | public class ProductB extends Product { | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | public class XmlFileParse implements IFileParse { | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     @Override | 
			
		
	
		
			
				
					|  |  |  |  |     public void method() { | 
			
		
	
		
			
				
					|  |  |  |  |         System.out.println("产品B"); | 
			
		
	
		
			
				
					|  |  |  |  |     public String parse() { | 
			
		
	
		
			
				
					|  |  |  |  |         return "Xml"; | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | ``` | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | ```java | 
			
		
	
		
			
				
					|  |  |  |  | //定义一个工厂用来生产产品 | 
			
		
	
		
			
				
					|  |  |  |  | public class Factory { | 
			
		
	
		
			
				
					|  |  |  |  |     public static Product createProduct(String type) { | 
			
		
	
		
			
				
					|  |  |  |  |         switch (type) { | 
			
		
	
		
			
				
					|  |  |  |  |             case "A": | 
			
		
	
		
			
				
					|  |  |  |  |                 return new ProductA(); | 
			
		
	
		
			
				
					|  |  |  |  |             case "B": | 
			
		
	
		
			
				
					|  |  |  |  |                 return new ProductB(); | 
			
		
	
		
			
				
					|  |  |  |  |             default: | 
			
		
	
		
			
				
					|  |  |  |  |                 return null; | 
			
		
	
		
			
				
					|  |  |  |  | public class FileParseFactory { | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     public IFileParse createFileParse(String name) { | 
			
		
	
		
			
				
					|  |  |  |  |         if ("xml".equals(name)) { | 
			
		
	
		
			
				
					|  |  |  |  |             return new XmlFileParse(); | 
			
		
	
		
			
				
					|  |  |  |  |         } else if ("json".equals(name)) { | 
			
		
	
		
			
				
					|  |  |  |  |             return new JsonFileParse(); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         return null; | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | ``` | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | ```java | 
			
		
	
		
			
				
					|  |  |  |  | //客户端根据传入的参数生成不同的产品 | 
			
		
	
		
			
				
					|  |  |  |  | public class Client { | 
			
		
	
		
			
				
					|  |  |  |  |     public static void main(String[] args) { | 
			
		
	
		
			
				
					|  |  |  |  |         ProductA productA = (ProductA) Factory.createProduct("A"); | 
			
		
	
		
			
				
					|  |  |  |  |         if (productA != null) { | 
			
		
	
		
			
				
					|  |  |  |  |             productA.method(); | 
			
		
	
		
			
				
					|  |  |  |  |         } else { | 
			
		
	
		
			
				
					|  |  |  |  |             System.out.println("不存在产品A"); | 
			
		
	
		
			
				
					|  |  |  |  | public class Resources { | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     public String parse(String name) { | 
			
		
	
		
			
				
					|  |  |  |  |         IFileParse fileParse = new FileParseFactory().createFileParse(name); | 
			
		
	
		
			
				
					|  |  |  |  |         if (fileParse != null) { | 
			
		
	
		
			
				
					|  |  |  |  |             return fileParse.parse(); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         throw new InvalidParameterException(); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | ``` | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 这种写法很简单,但是问题也是显而易见的,每当增加新产品时就得改代码,违反了开闭原则。 | 
			
		
	
		
			
				
					|  |  |  |  | 这个就是一个简单工厂方法的写法,不过呢,每次调用 createFileParse 都会创建一个新的 FileParse 类。实际上,如果 FileParse 可以复用,为了节省内存和对象创建的时间,我们可以把 FileParse 缓存起来。 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | ##### 工厂方法模式 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 将具体产品的创建延迟到具体工厂中完成,即由子类来决定应该实例化哪一个类。 | 
			
		
	
		
			
				
					|  |  |  |  | 具体写法就是: | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | ```java | 
			
		
	
		
			
				
					|  |  |  |  | //定义一个抽象工厂类 | 
			
		
	
		
			
				
					|  |  |  |  | public abstract class Factory { | 
			
		
	
		
			
				
					|  |  |  |  |     public abstract Product createProduct(); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | ``` | 
			
		
	
		
			
				
					|  |  |  |  | public class FileParseFactory { | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | ```java | 
			
		
	
		
			
				
					|  |  |  |  | //具体的工厂,生产不同的产品 | 
			
		
	
		
			
				
					|  |  |  |  | public class FactoryA extends Factory { | 
			
		
	
		
			
				
					|  |  |  |  |     @Override | 
			
		
	
		
			
				
					|  |  |  |  |     public Product createProduct() { | 
			
		
	
		
			
				
					|  |  |  |  |         return new ProductA(); | 
			
		
	
		
			
				
					|  |  |  |  |     private static HashMap<String, IFileParse> hashMap = new HashMap<>(4); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     static { | 
			
		
	
		
			
				
					|  |  |  |  |         hashMap.put("xml", new XmlFileParse()); | 
			
		
	
		
			
				
					|  |  |  |  |         hashMap.put("json", new JsonFileParse()); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | public class FactoryB extends Factory { | 
			
		
	
		
			
				
					|  |  |  |  |     @Override | 
			
		
	
		
			
				
					|  |  |  |  |     public Product createProduct() { | 
			
		
	
		
			
				
					|  |  |  |  |         return new ProductB(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     public IFileParse createFileParse(String name) { | 
			
		
	
		
			
				
					|  |  |  |  |         return hashMap.get(name); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | ``` | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | ##### 工厂方法模式 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | ```java | 
			
		
	
		
			
				
					|  |  |  |  | //用户决定要生产哪个产品 | 
			
		
	
		
			
				
					|  |  |  |  | public class Client { | 
			
		
	
		
			
				
					|  |  |  |  |     public static void main(String[] args) { | 
			
		
	
		
			
				
					|  |  |  |  |         Factory factory = new FactoryA(); | 
			
		
	
		
			
				
					|  |  |  |  |         ProductA productA = (ProductA) factory.createProduct(); | 
			
		
	
		
			
				
					|  |  |  |  |         productA.method(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         new FactoryB().createProduct().method(); | 
			
		
	
		
			
				
					|  |  |  |  | public class FileParseFactory { | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     public interface IFileParseFactory { | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         IFileParse createFileParse(); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     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() { | 
			
		
	
		
			
				
					|  |  |  |  |         //... | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | ``` | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | 
 |