工厂模式:在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
目标:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
分类:
1、简单工厂
2、工厂方法
3、抽象工厂
一、简单工厂
个人理解:多个类(类似于猫、狗),继承一个抽象类或者实现一个接口(动物),他们有相同的方法(比如叫),最后只需要一个工厂(动物),需要什么就制造什么(让哪个动物叫,就传入哪个动物)。
UML图解(画图工具出了点问题,就从别的地方找了个图,从哪借鉴的会在文章结尾标出):
(大家可以把猫狗鸡鸭想象成加减乘除,运算类就是动物类)
代码:
public class Main {
public static void main(String[] args) {
AnimalFactory.say(new Cat());
AnimalFactory.say(new Dog());
}
}
interface Animal{
void say();
}
class Cat implements Animal{
@Override
public void say() {
System.out.println("miaomiaomiao");
}
}
class Dog implements Animal{
@Override
public void say(){
System.out.println("wangwangwang");
}
}
class AnimalFactory{
public static void say(Animal a){
a.say();
}
}
优点:静态方法,根据条件判断需要哪个就用哪个
缺点:不同的产品有不同的参数,本工厂就不支持,扩展性差(违反开闭原则)
二、工厂方法
个人理解:所有的类都有对应的工厂,而这些工厂还有一个工厂(运算工厂,也属于运算类),当需要新的产品时,增加工厂类和对应的产品类即可
UML图解:
代码:
//动物
public interface Animal {
void say();
}
//猫
public class Cat implements Animal{
@Override
public void say() {
System.out.println("miao!");
}
}
//猫工厂
public class CatFactory {
public Animal create() {
System.out.println("a cat created!");
return new Cat();
}
}
//狗
public class Dog implements Animal{
@Override
public void say() {
System.out.println("wang!");
}
}
//狗工厂
public class DogFactory {
public Animal create() {
System.out.println("a dag created!");
return new Dog();
}
}
//需要什么就调用工厂生产什么并实现方法
public class Main {
public static void main(String[] args) {
Animal a = new CatFactory().create();
a.say();
}
}
优点:横向扩展比较方便,例如上图,需要添加新的运算具体的类的时候,添加类及其对应的工厂即可。
缺点:如果从一个对象的整体来拓展就很难实现(例如运算只是这个对象的一个属性,要是需要其他的属性一起修改),类似于产品一族整体修改
三、抽象工厂(在书籍讲解的时候工厂方法和抽象工厂是分开的,我给放到一起)
个人理解:
从上到下,先确定是这个工厂能产生什么(都有什么属性,例如代码就是交通工具和食物),然后创建具体的类,然后再创建不同的工厂去生产不同属性(交通工具和食物),最后需要什么工厂,就去调用什么工厂,将抽象变为好理解的。
UML图解(借鉴的图,看着有些复杂,只能细品了):
代码:
食物分类(可以创建多个食物)
//食物
public abstract class Food {
abstract void printName();
}
//面包(具体的食物)
public class Bread extends Food{
public void printName() {
System.out.println("我是面包");
}
}
//米饭(具体的食物)
public class Rice extends Food{
public void go() {
System.out.println("我是大米饭");
}
}
交通方式分类(可以创建多个交通方式)
public abstract class Vehicle { //interface
abstract void go();
}
public class Car extends Vehicle{
public void go() {
System.out.println("Car go wuwuwuwuw....");
}
}
public class Broom extends Vehicle{
public void go() {
System.out.println("Car go wuwuwuwuw....");
}
}
创建抽象工厂,分别生产这些东西
public abstract class AbastractFactory {
abstract Food createFood();
abstract Vehicle createVehicle();
}
创建具体的实现工厂(要生产什么的地方)
//现实世界人吃什么,用什么交通工具
public class ModernFactory extends AbastractFactory {
@Override
Food createFood() {
return new Bread();
}
@Override
Vehicle createVehicle() {
return new Car();
}
}
//魔法世界人吃什么,用什么交通工具
public class MagicFactory extends AbastractFactory {
@Override
Food createFood() {
return new Rice();
}
@Override
Vehicle createVehicle() {
return new Broom();
}
}
//最后怎样调用(调用实现之后的工厂,并且创建出需要的食物和交通工具)
public class Main {
public static void main(String[] args) {
//创建现实世界工厂
AbastractFactory f = new ModernFactory();
Vehicle c = f.createVehicle();
c.go();
Food b = f.createFood();
b.printName();
//创建魔法世界工厂
/*AbastractFactory af = new MagicFactory();
Vehicle vc = af.createVehicle();
vc.go();*/
}
}
优点:如果想拓展产品一族很方便,创建新的工厂即可,不用修改原来的代码(开闭原则)
缺点:如果想拓展具体产品一族中的一个属性不合适
最后总结:
工厂模式还是要自己去手敲一边代码才能理解,而且这个模式的产生的目的就是解耦,具体的实现方式大家可以学习下
Spring IOC(控制反转),Spring 将这个用的淋漓尽致。
最后感谢:芹泽 https://blog.csdn.net/u012218309/article/details/81333631 提供的UML图