系列文章目录
肝一肝设计模式【一】-- 单例模式 传送门
肝一肝设计模式【二】-- 工厂模式 传送门
文章目录
- 系列文章目录
- 前言
- 一、简单工厂模式
- 二、工厂方法模式
- 三、抽象工厂模式
- 写在最后
前言
在实际开发过程中,构建对象往往使用new的方式来构建,但随着开发时间的拉长,构建对象的逻辑慢慢会在很多类里使用,那就势必会产生大量的重复代码,那就意味着难以维护,所以我们想把创建对象的代码和业务逻辑分离,并通过一个统一的接口创建对象,然后把创建对象的逻辑封装起来,而这些就是工厂模式所解决的问题
一、简单工厂模式
我们拿动物世界举个栗子(最近陪女鹅看动画片看太多,脑子第一时间想到的只有动物o(* ̄3 ̄)o )
我们先定义一个Animal接口
public interface Animal {public void eat();
}
然后再创建两个实现类兔子和老虎
public class Rabbit implements Animal {@Overridepublic void eat() {System.out.println("我是兔子,我吃胡萝卜");}
}
public class Tiger implements Animal {@Overridepublic void eat() {System.out.println("我是老虎,我吃肉");}
}
再创建一个AnimalFactory工厂类,有两种方式实现:
- 使用逻辑判断方式
public class AnimalFactory {public Animal create(String name) {if("rabbit".equals(name)) {return new Rabbit();} else if("tiger".equals(name)) {return new Tiger();} else {System.out.println("啥也不是");return null;}}
}
然后我们测试一下:
public class SimpleFactoryTest {public static void main(String[] args) {AnimalFactory factory = new AnimalFactory();factory.create("rabbit").eat();}
}
也可将AnimalFactory工厂类的create()方法改为静态方法,这样调用就更方便一点。
- 使用反射方式
public class AnimalFactory {public Animal create(Class<? extends Animal> c){try {if (null != c) {return c.newInstance();}}catch (Exception e){e.printStackTrace();}return null;}
}
我们测试一下:
public class SimpleFactoryTest {public static void main(String[] args) {AnimalFactory factory = new AnimalFactory();Animal animal = factory.create(Tiger.class);animal.eat();}
}
简单工厂模式实质:是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。
二、工厂方法模式
在简单的工厂模式里,我们创建了一个类似工具的类来创建相应的具体类对象,但正因为其太过简单,不符合开闭原则。
工厂方法模式就是把简单工厂中具体的工厂类,划分成两层:抽象工厂层 + 具体的工厂子类层。
我们上面的工厂类进行拆分
- AnimalFactory(抽象工厂)
public abstract class AnimalFactory {public abstract Animal create();
}
- RabbitFactory(具体的工厂子类)‘
public class RabbitFactory extends AnimalFactory {@Overridepublic Animal create() {return new Rabbit();}
}
- TigerFactory(具体的工厂子类)
public class TigerFactory extends AnimalFactory {@Overridepublic Animal create() {return new Tiger();}
}
测试一下
public class FactoryMethodTest {public static void main(String[] args) {AnimalFactory factory = new RabbitFactory();Rabbit rabbit = factory.create();rabbit.eat();}
}
工厂方法模式实质:不仅仅产品要抽象, 工厂也需要抽象。这样的好处就是更拥抱变化,比如现在需要创建一个Cat对象,就不需要像简单工厂模式去修改create()方法,只需新增一个Cat工厂类即可,遵循了开闭原则。
三、抽象工厂模式
工厂方法模式中,具体工厂A和B,两者除了都是抽象工厂的子类,没有任何其他的交集,是完全独立的两个工厂。
那抽象工厂模式中,具体工厂之间就能产生交际。
抽象工厂模式是这么定义的,提供一个创建一系列相关或者相互依赖对象的接口,而无需指定它们具体的类。可以理解为将同一类的产品子类归为一类,让他们继承同一个抽象子类,把他们当做一个组。
比如我们新增一个Cat类,我们可以把猫和兔子分类成宠物类型,也可以把猫和老虎分类成猫科动物类型。
所以代码修改一下:
public class AbstractFactoryClient {public static void main(String[] args) {AnimalFactory factory = new PetFactory();factory.createPet().sayA();factory.createMaoke().sayB();factory = new MaokeFactory();factory.createPet().sayA();factory.createMaoke().sayB();}// 抽象工厂类public interface AnimalFactory {Pet createPet();Maoke createMaoke();}// 宠物分类抽象public interface Pet {void sayA();}// 猫科分类抽象public interface Maoke {void sayB();}// 宠物分类的兔子static class RabbitWithPet implements Pet {@Overridepublic void sayA() {System.out.println("我是宠物兔");}}// 宠物分类的猫static class CatWithPet implements Pet {@Overridepublic void sayA() {System.out.println("我是宠物猫");}}// 猫科分类的猫static class CatWithMaoke implements Maoke {@Overridepublic void sayB() {System.out.println("我能上树,所以我是猫科动物的老大");}}// 猫科分类的老虎static class TigerWithMaoke implements Maoke {@Overridepublic void sayB() {System.out.println("老大没教我怎么上树");}}// 具体工厂类(宠物)static class PetFactory implements AnimalFactory{@Overridepublic Pet createPet() {return new RabbitWithPet();}@Overridepublic Maoke createMaoke() {return new CatWithMaoke();}}// 具体工厂类(猫科)static class MaokeFactory implements AnimalFactory{@Overridepublic Pet createPet() {return new CatWithPet();}@Overridepublic Maoke createMaoke() {return new TigerWithMaoke();}}
}
在抽象工厂模式中,可以不需要知道产品是什么样的,只需要知道是用哪个工厂类就行了。也可以根据子类的共同特性,将它们设计在一起,组成一个相同类型组,就可以很方便的直接调用。但是相对的,产品族比较难以扩展,增加一个产品,就需要增加相应的接口和实现类。
写在最后
工厂模式关心的是最终创建的对象,而不关心创建的过程,这样做的优点是为创建对象提供统一的接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的,在此同时还能给系统带来更大的可扩展性和尽量少的修改量。