简单工厂,工厂方法,抽象工厂,三种工厂模式
简单工厂
简单工厂是真的简单,如果我们有N个类需要被工厂管理,那我们给N个类分配一个唯一标识,调用工厂方法需要传递标识,工厂根据传入的标识创建对象。这种做法的缺点很明显,扩展性太差!严重违反开闭原则。如果要是又新增M个类需要被工厂管理,那么还要去改工厂类代码。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package simplefactory_k;/* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2020-01-15 10:45 * @notify * @version 1.0 */ public class Airplane { }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package simplefactory_k;/* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2020-01-15 10:46 * @notify * @version 1.0 */ public class Rocket { }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package simplefactory_k;/* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2020-01-15 10:46 * @notify * @version 1.0 */ public class Screw { }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package simplefactory_k; /* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2020-01-15 10:46 * @notify * @version 1.0 */ public class SimpleFactoryK { public static Object getObject(String obj) { if (obj.equals("飞机")) { return new Airplane(); } else if (obj.equals("火箭")) { return new Rocket(); } else if (obj.equals("螺丝")) { return new Screw(); } else { return null; } } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package simplefactory_k; /* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2020-01-15 10:53 * @notify * @version 1.0 */ public class Main { public static void main(String[] args) { Object airplane = SimpleFactoryK.getObject("飞机"); System.out.println(airplane instanceof Airplane); Object rocket = SimpleFactoryK.getObject("火箭"); System.out.println(rocket instanceof Rocket); Object screw = SimpleFactoryK.getObject("螺丝"); System.out.println(screw instanceof Screw); } }
工厂方法
工厂方法弥补了简单工厂不易于扩展的缺点,给一个产品族定义一个接口,产品族下边定义具体的产品实现。(产品族的纵向的,接口和实现类,或者抽象类和子类)创建产品族工厂接口,不同的产品工厂创建不同的产品。苹果和香蕉都是都是水果族,苹果工厂生产苹果,香蕉工厂生产香蕉,而他们属于水果工厂。当我们需要增加另外一种水果,例如橘子,需要我们创建一个橘子类,和一个橘子类的工厂,这听起来好像又麻烦了许多。但是我们假设,创建一个类需要很多的参数,整体的创建需要写很多的代码。那创建一个工厂类是完全有必要的。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package factorymethod_k;/* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2020-01-15 14:22 * @notify * @version 1.0 */ public interface Fruiter { void product(); }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package factorymethod_k;/* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2020-01-15 14:24 * @notify * @version 1.0 */ public class Apple implements Fruiter { @Override public void product() { System.out.println("种出苹果"); } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package factorymethod_k;/* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2020-01-15 14:24 * @notify * @version 1.0 */ public class Banana implements Fruiter { @Override public void product() { System.out.println("种出香蕉"); } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package factorymethod_k;/* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2020-01-15 14:25 * @notify * @version 1.0 */ public interface Farm { Fruiter getBean(); }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package factorymethod_k;/* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2020-01-15 14:26 * @notify * @version 1.0 */ import factoryMethod.Fruit; public class AppleFarm implements Farm{ @Override public Fruiter getBean() { return new Apple(); } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package factorymethod_k;/* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2020-01-15 14:26 * @notify * @version 1.0 */ public class BananaFarm implements Farm{ @Override public Fruiter getBean() { return new Banana(); } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package factorymethod_k;/* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2020-01-15 14:29 * @notify * @version 1.0 */ public class Client { public static void main(String[] args) { Farm farm = new AppleFarm(); Fruiter fruiter = farm.getBean(); Farm farm2 = new BananaFarm(); Fruiter fruiter2 = farm2.getBean(); System.out.println(fruiter instanceof Apple); System.out.println(fruiter2 instanceof Banana); } }
抽象工厂
工厂方法对于单一产品族是够用了,但是如果是多产品族就不行了。思考一个场景,有一个水果族,和一个蔬菜族。水果和蔬菜都分热带种植环境,和常温种植环境。如果使用工厂方法,我们要怎么做呢?创建一个水果族接口,创建一个水果族工厂接口,创建一个蔬菜族的接口,一个蔬菜族工厂接口。但这显然是不符合实际逻辑的,热带水果和常温水果肯定不能在一个工厂被创建出来。热带蔬菜和常温蔬菜也是。于是我们需要横向抽取。热带水果,常温水果都是水果,热带蔬菜,常温蔬菜都是蔬菜。我们在园丁接口做抽取,有管理常温农作物的园丁和管理热带农作物的园丁。现在一个农场就可以创建两个族群的产品了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package abstractFactory; /* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2019-07-24 10:55 * @notify 蔬菜接口 * @version 1.0 */ public interface Veggie { }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package abstractFactory; /* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2019-07-24 10:58 * @notify 热带的蔬菜 * @version 1.0 */ import com.sun.org.apache.regexp.internal.RE; public class TropicalVeggie implements Veggie { private String name; public TropicalVeggie(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package abstractFactory; /* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2019-07-24 10:56 * @notify 北方的蔬菜 * @version 1.0 */ public class NorthernVeggie implements Veggie { private String name; public NorthernVeggie(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package abstractFactory; /* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2019-07-24 11:00 * @notify 水果接口 * @version 1.0 */ public interface Fruit { }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package abstractFactory; /* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2019-07-24 11:00 * @notify 北方的水果 * @version 1.0 */ public class NorthernFruit implements Fruit { private String name; public NorthernFruit(String name) { this.name = name; } public String getName(){ return name; } public void setName(String name){ this.name = name; } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package abstractFactory; /* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2019-07-24 11:02 * @notify 热带的水果 * @version 1.0 */ public class TropicalFruit implements Fruit { private String name; public TropicalFruit(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package abstractFactory; /* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2019-07-24 10:50 * @notify 园丁抽象类 * @version 1.0 */ public interface Gardener { }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package abstractFactory;/* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2019-07-24 10:50 * @notify 管理北方农场的园丁 * @version 1.0 */ public class NorthernGardener implements Gardener { // 北方的水果 public Fruit createFruit(String name) { return new NorthernFruit(name); } //北方的蔬菜 public Veggie createVeggie(String name) { return new NorthernVeggie(name); } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package abstractFactory; /* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2019-07-24 10:53 * @notify 管理热带农场的园丁 * @version 1.0 */ public class TropicalGardener implements Gardener{ //热带水果 public Fruit createFruit(String name){ return new TropicalFruit(name); } //热带蔬菜 public Veggie createVeggie(String name){ return new TropicalVeggie(name); } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package abstractFactory;/* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2019-07-24 12:28 * @notify * @version 1.0 */ import junit.framework.TestCase; public class AbstractFactoryTest extends TestCase { public void testCreate(){ TropicalGardener tropicalGardener = new TropicalGardener(); Fruit fruit1 = tropicalGardener.createFruit("热带水果"); Veggie veggie1 = tropicalGardener.createVeggie("热带蔬菜"); assertTrue(fruit1 instanceof TropicalFruit); assertTrue(veggie1 instanceof TropicalVeggie); NorthernGardener northernGardener = new NorthernGardener(); Fruit fruit2 = northernGardener.createFruit("北方水果"); Veggie veggie2 = northernGardener.createVeggie("北方蔬菜"); assertTrue(fruit2 instanceof NorthernFruit); assertTrue(veggie2 instanceof NorthernVeggie); } }