[关闭]
@BertLee 2017-08-08T22:44:47.000000Z 字数 5192 阅读 1188

会生孩子的工厂模式

序言

  工厂模式作为创建多例对象的一种设计思想,避免了面向过程一泻千里的糟糕写法,扩展性和可维护性都很强,值得我们好好学习。
  工厂模式大致分为3类,分别是简单工厂、工厂方法、抽象工厂,下面就自己的理解,总结一下。入笔之前,先阐述几个不知所云的概念。
- 抽象工厂类角色:接口或者抽象类,所有的具体工厂类都要实现或继承该类
- 具体工厂类角色:具体类,new对象的逻辑都在这里,调用者只需调用该静态方法
- 抽象产品角色:接口或者抽象类,为调用者提供行为方法
- 具体产品角色:具体类,真正被new的对象,调用者无需亲自创建,一切皆由静态工厂方法处理

1. 简单工厂

  简单工厂的基本结构如下图:

  套路:
    1. 要生成多个相似功能的产品,但不同的产品的具体功能不同,即要有继承或者实现接口
    2. 添加1个具体工厂类,添加1个静态工厂方法

  1. /**
  2. * 抽象产品角色
  3. */
  4. public interface Fruit {
  5. void grow();
  6. }
  1. /**
  2. * 具体产品角色
  3. */
  4. public class Apple implements Fruit {
  5. public void grow() {
  6. System.out.println("apple growed");
  7. }
  8. }
  1. /**
  2. * 具体产品橘色
  3. */
  4. public class Banana implements Fruit {
  5. public void grow() {
  6. System.out.println("banana growed");
  7. }
  8. }
  1. /**
  2. * 工厂类
  3. */
  4. public class FruitFactory {
  5. public static Fruit createFruit(String fruitName){
  6. if("apple".equals(fruitName)){
  7. return new Apple();
  8. }
  9. if("banaa".equals(fruitName)){
  10. return new Banana();
  11. }
  12. throw new RuntimeException("fruitName not exits");
  13. }
  14. public static <T extends Fruit> T createFruit(Class<T> clazz){
  15. T fruit = null;
  16. try {
  17. fruit = (T) Class.forName(clazz.getName()).newInstance();
  18. return fruit;
  19. } catch (InstantiationException e) {
  20. e.printStackTrace();
  21. } catch (IllegalAccessException e) {
  22. e.printStackTrace();
  23. } catch (ClassNotFoundException e) {
  24. e.printStackTrace();
  25. }
  26. return null;
  27. }
  28. }
  1. public class SimpleFactoryTest {
  2. @Test
  3. public void testSimpleFactory(){
  4. Fruit apple = FruitFactory.createFruit("apple");
  5. apple.grow();
  6. Banana banana = FruitFactory.createFruit(Banana.class);
  7. banana.grow();
  8. }
  9. }

  吹牛:增加工厂类后,调用者无需亲自创建对象,通过静态工厂方法拿到对象后,直接调用其行为方法,如果再增加葡萄产品时,只需写一个Grape类,实现Fruit接口,在Factory增加1个if即可,无需修改客户端代码。不好的地方在于,静态工厂方法承担的任务太重,当产品越来越多时,该方法会变得又臭又长。

2. 工厂方法

  工厂方法基本结构图如下:







套路:
  1. 要生产多个相似功能的产品,但通过分类,还可以分为几大类的生产者
  2. 添加1个抽象工厂类或者接口,添加多个具体生产工厂,工厂里的方法都是实例方法
  3. 客户端调用时,直接new对应的factory,然后传参数调用其实例方法

  1. /**
  2. * 产品接口
  3. */
  4. public interface Animal {
  5. void run();
  6. }
  1. /**
  2. * 具体产品,4条腿
  3. */
  4. public class Panada implements Animal{
  5. public void run() {
  6. System.out.println("panada is running ...");
  7. }
  8. }
  1. /**
  2. * 具体产品,4条腿
  3. */
  4. public class Tigger implements Animal{
  5. public void run() {
  6. System.out.println("tigger is running ...");
  7. }
  8. }
  1. /**
  2. * 具体产品,2条腿
  3. */
  4. public class Human implements Animal{
  5. public void run() {
  6. System.out.println("human is runging ....");
  7. }
  8. }
  1. /**
  2. * 具体产品,2条腿
  3. */
  4. public class Penguin implements Animal {
  5. public void run() {
  6. System.out.println("penguin is running ...");
  7. }
  8. }
  1. /**
  2. * 抽象工厂接口
  3. */
  4. public interface AnimalFactory {
  5. Animal createAnimal(String animalName);
  6. }
  1. /**
  2. * 具体工厂,两条腿
  3. */
  4. public class TwoLegsAnimalFactory implements AnimalFactory{
  5. public Animal createAnimal(String animalName) {
  6. if("human".equals(animalName)){
  7. return new Human();
  8. }
  9. if("penguin".equals(animalName)){
  10. return new Penguin();
  11. }
  12. throw new RuntimeException("not extists this four legs");
  13. }
  14. }
  1. /**
  2. * 具体工厂,4条腿
  3. */
  4. public class FourLegsAnimalFactory implements AnimalFactory{
  5. public Animal createAnimal(String animalName) {
  6. if("tigger".equals(animalName)){
  7. return new Tigger();
  8. }
  9. if("panada".equals(animalName)){
  10. return new Panada();
  11. }
  12. throw new RuntimeException("not extists this four legs");
  13. }
  14. }
  1. /**
  2. * 测试工厂方法
  3. */
  4. public class FactoryMethodTest {
  5. @Test
  6. public void testFactoryMethod(){
  7. AnimalFactory fourLegsAnimalFactory = new FourLegsAnimalFactory();
  8. fourLegsAnimalFactory.createAnimal("tigger").run();
  9. fourLegsAnimalFactory.createAnimal("panada").run();
  10. TwoLegsAnimalFactory twoLegsAnimalFactory = new TwoLegsAnimalFactory();
  11. twoLegsAnimalFactory.createAnimal("penguin").run();
  12. twoLegsAnimalFactory.createAnimal("human").run();
  13. }
  14. }

  吹牛:如果系统需要增加一个新产品,那么只需要向系统增加一个具体产品类,及其对应的具体工厂类,无需修改抽象工厂类,无需修改其它具体工厂类,也无需修改客户端。

3. 抽象工厂

抽象工厂的具体结构图如下:



  套路:
    1. 添加新的产品,增加抽象产品,以及其对应的具体产品类
    2. 在工厂方法模式下,修改具体工厂方法名称,用产品名称命名
    3. 在抽象工厂接口里添加生产具体产品的方法

  1. /**
  2. * 抽象产品-电脑
  3. */
  4. public interface Computer {
  5. public String getComputerInfo();
  6. }
  1. /**
  2. * 抽象产品-手机
  3. */
  4. public interface Phone {
  5. public String getPhoneInfo();
  6. }
  1. /**
  2. * 具体产品-苹果电脑
  3. */
  4. public class AppleComputer implements Computer{
  5. public String getComputerInfo() {
  6. return "mac pro 12 is using";
  7. }
  8. }
  1. /**
  2. * 具体工厂-三星电脑
  3. */
  4. public class SamsungComputer implements Computer{
  5. public String getComputerInfo() {
  6. return "samsung 900X3N-K09 is using";
  7. }
  8. }
  1. /**
  2. * 具体产品-苹果手机
  3. */
  4. public class ApplePhone implements Phone{
  5. public String getPhoneInfo() {
  6. return "iphone 8 is using";
  7. }
  8. }
  1. /**
  2. * 具体产品-三星手机
  3. */
  4. public class SamsungPhone implements Phone {
  5. public String getPhoneInfo() {
  6. return "samsung galaxy s8 is usging";
  7. }
  8. }
  1. /**
  2. * 抽象工厂
  3. */
  4. public interface ElectronicFactory {
  5. public Phone createPhone();
  6. public Computer createComputer();
  7. }
  1. /**
  2. * 具体工厂-苹果,以品牌厂家分类,即apple和samsung,而不是具体产品分类,即computer和phone
  3. */
  4. public class AppleFactory implements ElectronicFactory{
  5. public Phone createPhone() {
  6. return new ApplePhone();
  7. }
  8. public Computer createComputer() {
  9. return new AppleComputer();
  10. }
  11. }
  1. /**
  2. * 具体工厂-三星,以品牌厂家分类,即apple和samsung,而不是具体产品分类,即computer和phone
  3. */
  4. public class SamsungFactory implements ElectronicFactory{
  5. public Phone createPhone() {
  6. return new SamsungPhone();
  7. }
  8. public Computer createComputer() {
  9. return new SamsungComputer();
  10. }
  11. }
  1. /**
  2. * 抽象工厂测试
  3. */
  4. public class AbstractFactoryTest {
  5. @Test
  6. public void testAbstractFactory(){
  7. ElectronicFactory appleFactory = new AppleFactory();
  8. appleFactory.createPhone().getPhoneInfo();
  9. appleFactory.createComputer().getComputerInfo();
  10. ElectronicFactory samsungFactory = new SamsungFactory();
  11. samsungFactory.createPhone().getPhoneInfo();
  12. samsungFactory.createComputer().getComputerInfo();
  13. }
  14. }

  吹牛:如果系统需要增加一个新的产品族,如新厂家或者新品牌,再增加一个品牌的具体工厂方法即可,无需修改原来的抽象工厂类和具体工厂类,也无需修改客户端,缺点是如果增加一个新的产品时,即添加一个抽象类及其对应的具体产品类的产品树时,原来的抽象工厂和具体工厂都要修改。

4. 总结

后记

  转载时,注明出处是人格的一种体现。
  https://www.zybuluo.com/BertLee/note/837738
  能力有限,如有纰漏,请在评论区指出,老朽虽一把年纪,必当感激涕零,泪如雨下。若有满嘴喷粪撕逼者,一律拉黑、举报,并移交阎王爷处理。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注