1. 简单工厂模式(Simple Factory Parrent)
/** * 在讲工厂方法模式之前,先将一个简单工厂模式,这个模式实现了对象和被调用者的解耦,但是依旧有很多问题,工厂方法模式就是 * 从建工工厂模式演变过来的 * * 简单工厂模式: * 简单工厂模式就是由一个工厂类根据传入的参数决定创建哪一种的产品类 * 适用场景: * 适用于业务逻辑比较简单的情景 * * 第一步: 假设要实现一个描述动物信息功能,我们知道首先要创建一个抽象类 IAnimal, 然后想具体描述什么动物, * 就去继承抽象类,再去添加自己本身独有的属性,我们这里实现一个猫 Cat 和狗 Dog * * 第二步 : 当我们想去获得这两个动物的信息和特长的时候,需要分别去 new 这两个对象,比较麻烦,当我们想看哪一个动物的信息的时候, * 还需要自己去创建对象,我们想的是告诉别人我要看哪个动物的信息,他就给我返回这个动物的信息,这里的别人指的就是"工厂", * 接下来我们来实现这个功能,首先需要一个工厂类 AnimalFactory,然后我们写一个测试类 TestFactoryMethod, * 我们把具体的获取对象实例的方法交给工厂去做,这样更加符合正常的业务逻辑,但它也有一个问题,比如我们想添加一个动物的信息, * 我们需要创建一个动物的具体实现类,还要去工厂中添加信息,当业务逻辑比较复杂的时候,这种做法会让程序变得很混乱,因为一个项目中可能 * 有几百个工厂,当我们要去实现一个新的功能的时候,可能要修改很多类,这不符合设计模式的六大原则中的开闭原则 * * 所以"简单工厂模式"适用于不会再添加新的功能的小项目中,这种工厂类也被称为全能类,意思是设计的时候就已经考虑好了所有情况 * * Created by Demon-Coffee on 2018/1/13 0013. */
public interface IAnimal { /** * 动物特长 */ String getSpecialty(String specialty); /** * 动物属性 */ String getInfo(); }
/** * Created by Demon-Coffee on 2018/1/13 0013. */ public class Cat implements IAnimal { /** * 猫的特长 */ public String getSpecialty(String specialty) { return "我会" + specialty; } public String getInfo() { return "我是一只可爱的小猫咪"; } }
/** * Created by Demon-Coffee on 2018/1/13 0013. */ public class Dog implements IAnimal { /** * 狗的特长 */ public String getSpecialty(String specialty) { return "我会" + specialty; } public String getInfo() { return "我是一条单身狗"; } }
/** * Created by Demon-Coffee on 2018/1/13 0013. */ public class AnimalFactory { /** * 获取动物信息实例 * @param animalType 动物类型:dog/cat */ public static IAnimal getInstance(String animalType) throws Exception { switch (animalType.toLowerCase()) { case "dog": return new Dog(); case "cat": return new Cat(); default: throw new RuntimeException("你要查找的动物没有入库"); } } }
/** * 这样做的好处是,屏蔽了底层的创建过程,使用者只需要关心实现即可,不需要关心对象是怎么创建的 * 缺点也很明显,耦合性很高,当出现一个新的动物的时候,需要修改工厂类,违反了 "开闭原则", * 之后将会通过工厂方法模式来解决 "开闭原则" 问题 * * Created by Demon-Coffee on 2018/1/13 0013. */ public class TestSimpleFactory { public static void main(String[] args) throws Exception { // 我想知道狗的信息 IAnimal animal = AnimalFactory.getInstance("dog"); System.out.println(String.format("Dog:%s", animal.getInfo())); System.out.println(String.format("Dog:%s", animal.getSpecialty("咬人"))); // 我想知道猫的信息 animal = AnimalFactory.getInstance("cat"); System.out.println(String.format("Cat:%s", animal.getInfo())); System.out.println(String.format("Cat:%s", animal.getSpecialty("上树"))); AnimalFactory.getInstance("pig"); // 这里会报错,因为工厂不支持这个动物的创建 } /* 程序输出: 我是一条单身狗 我会咬人 我是一只可爱的小猫咪 我会上树 Exception in thread "main" java.lang.RuntimeException: 你要查找的动物没有入库 at com.demon.factoryMethod.example1.AnimalFactory.getInstance(AnimalFactory.java:19) at com.demon.factoryMethod.example1.TestFactoryMethod.main(TestFactoryMethod.java:19) */ }
2. 工厂方法模式(Factory Method Parrent)
- 工厂方法模式是简单工厂模式的加强版,解决了简单工厂模式的一些缺点,比如"开闭原则",它不需要修改原来的代码,只需要添加新的代码就可以了,它的层次结构更加复杂,
适用于比较复杂的场景
- 实现原理是对简单工厂模式进行了抽象,抽象类 Factory 将不再负责具体的生产,只是制定一些规则,具体的生产由继承了它的具体工厂类去做,这个时候,其实就是一个具
体的对象对应一个具体的工厂类,一个抽象类对应一个抽象对象类,添加的代码如下,这样的好处是我们每次增加对象只需要修改对象具体实现类,和具体工厂类这两个类,这样
有一个缺点就是,逻辑判断放在了客户端,客户端需要修改代码,代码片段如下:
/** * 工厂方法模式: * 工厂方法模式是简单工厂模式的加强版,解决了简单工厂模式的一些缺点,比如"开闭原则",它不需要修改原来的代码,只需要添加 * 新的代码就可以了,它的层次结构更加复杂 * 适用场景: * 比较复杂的场景,比如工厂生产的对象可能会有新增,或删除 * 实现原理: * 对简单工厂模式进行了抽象,抽象类 Factory 将不再负责具体的生产,只是制定一些规则,具体的生产由继承了它的具体工厂类去 * 做,这个时候,其实就是一个具体的对象对应一个具体的工厂类,一个抽象类对应一个抽象对象类,添加的代码如下,这样的好处是我 * 们每次增加对象只需要修改对象具体实现类,和具体工厂类这两个类,这样也会有一个缺点就是,逻辑判断放在了客户端,客户端需要 * 修改代码 * 第一步: * 将example1中的 Cat,Dog,IAnimal 拷贝过来,然后创建一个工厂接口类 IAnimalFactoryMethod * 第二步: * 新建 Dog 的工厂类和 Cat 的工厂类,继承 IAnimalFactoryMethod * * Created by Demon-Coffee on 2018/1/13 0013. */
public interface IAnimalFactoryMethod { /** * 生产对象 * @param animalType 动物类型:dog/cat */ IAnimal getInstance(String animalType) throws Exception; }
public class DogFactoryMethod implements IAnimalFactoryMethod { @Override public IAnimal getInstance(String animalType) throws Exception { if(animalType.toLowerCase().equals("dog")) { return new Dog(); } throw new Exception("你要查找的动物没有入库"); } }
public class CatFactoryMethod implements IAnimalFactoryMethod { @Override public IAnimal getInstance(String animalType) throws Exception { if(animalType.toLowerCase().equals("cat")) { return new Cat(); } throw new Exception("你要查找的动物没有入库"); } }
/** * 这样做的好处是,屏蔽了底层的创建过程,使用者只需要关心实现即可,不需要关心对象是怎么创建的 * 缺点也很明显,耦合性很高,当出现一个新的动物的时候,需要修改工厂类,违反了 "开闭原则", * 之后将会通过工厂方法模式来解决 "开闭原则" 问题 * * Created by Demon-Coffee on 2018/1/13 0013. */ public class TestFactoryMethod { public static void main(String[] args) throws Exception { // 我想知道狗的信息 DogFactoryMethod dogFactoryMethod = new DogFactoryMethod(); IAnimal animal = dogFactoryMethod.getInstance("dog"); System.out.println(String.format("Dog:%s", animal.getInfo())); System.out.println(String.format("Dog:%s", animal.getSpecialty("咬人"))); // 我想知道猫的信息 CatFactoryMethod catFactoryMethod = new CatFactoryMethod(); animal = catFactoryMethod.getInstance("cat"); System.out.println(String.format("Cat:%s", animal.getInfo())); System.out.println(String.format("Cat:%s", animal.getSpecialty("上树"))); } /* 程序输出: Dog:我是一条单身狗 Dog:我会咬人 Cat:我是一只可爱的小猫咪 Cat:我会上树 */ }
具体代码在 Git:JAVA 设计模式