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

套路:
1. 要生成多个相似功能的产品,但不同的产品的具体功能不同,即要有继承或者实现接口
2. 添加1个具体工厂类,添加1个静态工厂方法
/*** 抽象产品角色*/public interface Fruit {void grow();}
/*** 具体产品角色*/public class Apple implements Fruit {public void grow() {System.out.println("apple growed");}}
/*** 具体产品橘色*/public class Banana implements Fruit {public void grow() {System.out.println("banana growed");}}
/*** 工厂类*/public class FruitFactory {public static Fruit createFruit(String fruitName){if("apple".equals(fruitName)){return new Apple();}if("banaa".equals(fruitName)){return new Banana();}throw new RuntimeException("fruitName not exits");}public static <T extends Fruit> T createFruit(Class<T> clazz){T fruit = null;try {fruit = (T) Class.forName(clazz.getName()).newInstance();return fruit;} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}return null;}}
public class SimpleFactoryTest {@Testpublic void testSimpleFactory(){Fruit apple = FruitFactory.createFruit("apple");apple.grow();Banana banana = FruitFactory.createFruit(Banana.class);banana.grow();}}
吹牛:增加工厂类后,调用者无需亲自创建对象,通过静态工厂方法拿到对象后,直接调用其行为方法,如果再增加葡萄产品时,只需写一个Grape类,实现Fruit接口,在Factory增加1个if即可,无需修改客户端代码。不好的地方在于,静态工厂方法承担的任务太重,当产品越来越多时,该方法会变得又臭又长。
工厂方法基本结构图如下:
套路:
1. 要生产多个相似功能的产品,但通过分类,还可以分为几大类的生产者
2. 添加1个抽象工厂类或者接口,添加多个具体生产工厂,工厂里的方法都是实例方法
3. 客户端调用时,直接new对应的factory,然后传参数调用其实例方法
/*** 产品接口*/public interface Animal {void run();}
/*** 具体产品,4条腿*/public class Panada implements Animal{public void run() {System.out.println("panada is running ...");}}
/*** 具体产品,4条腿*/public class Tigger implements Animal{public void run() {System.out.println("tigger is running ...");}}
/*** 具体产品,2条腿*/public class Human implements Animal{public void run() {System.out.println("human is runging ....");}}
/*** 具体产品,2条腿*/public class Penguin implements Animal {public void run() {System.out.println("penguin is running ...");}}
/*** 抽象工厂接口*/public interface AnimalFactory {Animal createAnimal(String animalName);}
/*** 具体工厂,两条腿*/public class TwoLegsAnimalFactory implements AnimalFactory{public Animal createAnimal(String animalName) {if("human".equals(animalName)){return new Human();}if("penguin".equals(animalName)){return new Penguin();}throw new RuntimeException("not extists this four legs");}}
/*** 具体工厂,4条腿*/public class FourLegsAnimalFactory implements AnimalFactory{public Animal createAnimal(String animalName) {if("tigger".equals(animalName)){return new Tigger();}if("panada".equals(animalName)){return new Panada();}throw new RuntimeException("not extists this four legs");}}
/*** 测试工厂方法*/public class FactoryMethodTest {@Testpublic void testFactoryMethod(){AnimalFactory fourLegsAnimalFactory = new FourLegsAnimalFactory();fourLegsAnimalFactory.createAnimal("tigger").run();fourLegsAnimalFactory.createAnimal("panada").run();TwoLegsAnimalFactory twoLegsAnimalFactory = new TwoLegsAnimalFactory();twoLegsAnimalFactory.createAnimal("penguin").run();twoLegsAnimalFactory.createAnimal("human").run();}}
吹牛:如果系统需要增加一个新产品,那么只需要向系统增加一个具体产品类,及其对应的具体工厂类,无需修改抽象工厂类,无需修改其它具体工厂类,也无需修改客户端。
抽象工厂的具体结构图如下:
套路:
1. 添加新的产品,增加抽象产品,以及其对应的具体产品类
2. 在工厂方法模式下,修改具体工厂方法名称,用产品名称命名
3. 在抽象工厂接口里添加生产具体产品的方法
/*** 抽象产品-电脑*/public interface Computer {public String getComputerInfo();}
/*** 抽象产品-手机*/public interface Phone {public String getPhoneInfo();}
/*** 具体产品-苹果电脑*/public class AppleComputer implements Computer{public String getComputerInfo() {return "mac pro 12 is using";}}
/*** 具体工厂-三星电脑*/public class SamsungComputer implements Computer{public String getComputerInfo() {return "samsung 900X3N-K09 is using";}}
/*** 具体产品-苹果手机*/public class ApplePhone implements Phone{public String getPhoneInfo() {return "iphone 8 is using";}}
/*** 具体产品-三星手机*/public class SamsungPhone implements Phone {public String getPhoneInfo() {return "samsung galaxy s8 is usging";}}
/*** 抽象工厂*/public interface ElectronicFactory {public Phone createPhone();public Computer createComputer();}
/*** 具体工厂-苹果,以品牌厂家分类,即apple和samsung,而不是具体产品分类,即computer和phone*/public class AppleFactory implements ElectronicFactory{public Phone createPhone() {return new ApplePhone();}public Computer createComputer() {return new AppleComputer();}}
/*** 具体工厂-三星,以品牌厂家分类,即apple和samsung,而不是具体产品分类,即computer和phone*/public class SamsungFactory implements ElectronicFactory{public Phone createPhone() {return new SamsungPhone();}public Computer createComputer() {return new SamsungComputer();}}
/*** 抽象工厂测试*/public class AbstractFactoryTest {@Testpublic void testAbstractFactory(){ElectronicFactory appleFactory = new AppleFactory();appleFactory.createPhone().getPhoneInfo();appleFactory.createComputer().getComputerInfo();ElectronicFactory samsungFactory = new SamsungFactory();samsungFactory.createPhone().getPhoneInfo();samsungFactory.createComputer().getComputerInfo();}}
吹牛:如果系统需要增加一个新的产品族,如新厂家或者新品牌,再增加一个品牌的具体工厂方法即可,无需修改原来的抽象工厂类和具体工厂类,也无需修改客户端,缺点是如果增加一个新的产品时,即添加一个抽象类及其对应的具体产品类的产品树时,原来的抽象工厂和具体工厂都要修改。
转载时,注明出处是人格的一种体现。
https://www.zybuluo.com/BertLee/note/837738
能力有限,如有纰漏,请在评论区指出,老朽虽一把年纪,必当感激涕零,泪如雨下。若有满嘴喷粪撕逼者,一律拉黑、举报,并移交阎王爷处理。