【Java】设计模式(1)—工厂模式

1.设计模式的分类

总体来说设计模式分为三大类:

创建型模式,共五种:工厂方法模式抽象工厂模式、单例模式、建造者模式、原型模式。

结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

这里我们先来聊聊工厂方法模式。

简单工厂模式、工厂方法模式、抽象工厂模式,都是属于创建型设计模式。严格上来说,简单工厂模式不属于23设计模式之一,因为它违背了开闭原则。

2.简单工厂模式(静态工厂模式)

先弄一个冰淇淋接口+3个口味的冰淇淋实现类

/**
 * 冰淇淋接口、没有具体口味
 * @author xingyanan01-lhq
 */
public interface IceCream {
	public void makeIceCream();

}
/**
 * 苹果口味冰淇淋
 * @author xingyanan01-lhq
 */
public class AppleIceCream implements IceCream{

	@Override
	public void makeIceCream() {
		System.out.println("制作一个苹果口味冰淇淋");
	}

}
/**
 * 橘子口味冰淇淋
 * @author xingyanan01-lhq
 */
public class OrangeIceCream implements IceCream {

	@Override
	public void makeIceCream() {
		System.out.println("制作一个橘子口味冰淇淋");
	}

}
/**
 * 香蕉口味冰淇淋
 * @author xingyanan01-lhq
 */
public class BananaIceCream implements IceCream{

	@Override
	public void makeIceCream() {
		System.out.println("制作一个香蕉口味冰淇淋");
	}

}

造一个冰淇淋工厂,根据不同口味口令KEY来判断具体生产什么口味的冰淇淋

/**
 * 冰淇淋工厂,根据传递的key来返回不同的冰淇淋类
 * @author xingyanan01-lhq
 */
public class IceCreamFactory {
	//这里注意一下,用静态static方法
	public static IceCream creamIceCream(String key){
		IceCream iceCream = null;
		if("apple".equals(key)) {
			iceCream = new AppleIceCream();
		}
		if("orange".equals(key)) {
			iceCream = new OrangeIceCream();
		}
		if("banana".equals(key)) {
			iceCream = new BananaIceCream();
		}
		return iceCream;
	}
}

具体实现:

/**
 * 客户端执行
 * @author xingyanan01-lhq
 */
 public static void main(String[] args) {
    	// 我告诉工厂,我想要个苹果口味冰淇淋
    	IceCream appleIceCream = IceCreamFactory.creamIceCream("apple");
    	appleIceCream.makeIceCream();
    	// 我告诉工厂,我想要个橘子口味冰淇淋
    	IceCream orangeIceCream = IceCreamFactory.creamIceCream("orange");
    	orangeIceCream.makeIceCream();
    	// 我告诉工厂,我想要个香蕉口味冰淇淋
    	IceCream bananaIceCream = IceCreamFactory.creamIceCream("banana");
    	bananaIceCream.makeIceCream();
  }

【Java】设计模式(1)—工厂模式_第1张图片
这里我们用一个冰淇淋工厂管理所有口味的冰淇淋,我们只需要new一个冰淇淋工厂,就能通过key获取所有口味的冰淇淋。

3.工厂方法模式

简单工厂模式确实很方便,但是每次新增一个口味的冰淇淋都需要改动整个工厂的原有代码。
那不如我们一个冰淇淋工厂只生产一种冰淇淋,需要新增口味就直接新建一个工厂。

还是要弄一个冰淇淋接口+3个口味的冰淇淋实现类

/**
 * 冰淇淋接口、没有具体口味
 * @author xingyanan01-lhq
 */
public interface IceCream {
	public void makeIceCream();
}
/**
 * 苹果口味冰淇淋
 * @author xingyanan01-lhq
 */
public class AppleIceCream implements IceCream{

	@Override
	public void makeIceCream() {
		System.out.println("制作一个苹果口味冰淇淋");
	}

}
/**
 * 橘子口味冰淇淋
 * @author xingyanan01-lhq
 */
public class OrangeIceCream implements IceCream {

	@Override
	public void makeIceCream() {
		System.out.println("制作一个橘子口味冰淇淋");
	}

}
/**
 * 香蕉口味冰淇淋
 * @author xingyanan01-lhq
 */
public class BananaIceCream implements IceCream{

	@Override
	public void makeIceCream() {
		System.out.println("制作一个香蕉口味冰淇淋");
	}

}

造一个冰淇淋工厂接口+3个冰淇淋对应口味的冰淇淋工厂

/**
 * 冰淇淋工厂接口,没有具体口味
 * @author xingyanan01-lhq
 */
public interface IceCreamFactory {
	public IceCream creamIceCream();
}
/**
 * 苹果冰淇淋工厂
 * @author xingyanan01-lhq
 */
public class AppleIceCreamFactory implements IceCreamFactory{
	@Override
	public IceCream creamIceCream() {
		return new AppleIceCream();
	}
}
/**
 * 橘子冰淇淋工厂
 * @author xingyanan01-lhq
 */
public class OrangeIceCreamFactory implements IceCreamFactory{
	@Override
	public IceCream creamIceCream() {
		return new OrangeIceCream();
	}
}
/**
 * 香蕉冰淇淋工厂
 * @author xingyanan01-lhq
 */
public class BananaIceCreamFactory implements IceCreamFactory{
	@Override
	public IceCream creamIceCream() {
		return new BananaIceCream();
	}
}

具体实现:

/**
 * 客户端执行
 * @author xingyanan01-lhq
 */
public static void main(String[] args) {
    	// 我去苹果口味冰淇淋工厂,要一个冰淇淋
    	AppleIceCreamFactory appleIceCreamFactory = new AppleIceCreamFactory();
    	IceCream appleIceCream = appleIceCreamFactory.creamIceCream();
    	appleIceCream.makeIceCream();
    	// 我去橘子口味冰淇淋工厂,要一个冰淇淋
    	OrangeIceCreamFactory orangeIceCreamFactory = new OrangeIceCreamFactory();
    	IceCream orangeIceCream = orangeIceCreamFactory.creamIceCream();
    	orangeIceCream.makeIceCream();
    	// 我去香蕉口味冰淇淋工厂,要一个冰淇淋
    	BananaIceCreamFactory bananaIceCreamFactory = new BananaIceCreamFactory();
    	IceCream bananaIceCream = bananaIceCreamFactory.creamIceCream();
    	bananaIceCream.makeIceCream();
 }

【Java】设计模式(1)—工厂模式_第2张图片
这里我们是每个口味的冰淇淋都有对应的工厂,后续如果想新增一个口味的冰淇淋,只需要加一个工厂,无需改动其它的已有的工厂
看到这里你可能会有疑惑,这样的话一个口味的冰淇淋对应一个工厂,我还用工厂干嘛?直接new冰淇淋不好吗?
别着急,让我们带着这个疑问往后看~

4.抽象工厂模式

如果现在冰淇淋有规格要求了,有大冰淇淋小冰淇淋的,这可咋办?
还是要弄1个大冰淇淋接口+1个小冰淇淋接口+对应3个口味的6个具体冰淇淋实现类

/**
 * 大冰淇淋、没有具体口味
 * @author xingyanan01-lhq
 */
public interface BigIceCream {
	public void makeIceCream();
}
/**
 * 小冰淇淋、没有具体口味
 * @author xingyanan01-lhq
 */
public interface SmallIceCream {
	public void makeIceCream();
}
/**
 * 大苹果口味冰淇淋
 * @author xingyanan01-lhq
 */
public class BigAppleIceCream implements BigIceCream{
	@Override
	public void makeIceCream() {
		System.out.println("制作一个大号苹果口味冰淇淋");
	}
}
/**
 * 小苹果口味冰淇淋
 * @author xingyanan01-lhq
 */
public class SmallAppleIceCream implements SmallIceCream{
	@Override
	public void makeIceCream() {
		System.out.println("制作一个小号苹果口味冰淇淋");
	}
}
/**
 * 大橘子口味冰淇淋
 * @author xingyanan01-lhq
 */
public class BigOrangeIceCream implements BigIceCream{
	@Override
	public void makeIceCream() {
		System.out.println("制作一个大号橘子口味冰淇淋");
	}
}
/**
 * 小橘子口味冰淇淋
 * @author xingyanan01-lhq
 */
public class SmallOrangeIceCream implements SmallIceCream{
	@Override
	public void makeIceCream() {
		System.out.println("制作一个小号橘子口味冰淇淋");
	}
}
/**
 * 大香蕉口味冰淇淋
 * @author xingyanan01-lhq
 */
public class BigBananaIceCream implements BigIceCream{
	@Override
	public void makeIceCream() {
		System.out.println("制作一个大号香蕉口味冰淇淋");
	}
}
/**
 * 小香蕉口味冰淇淋
 * @author xingyanan01-lhq
 */
public class SmallBananaIceCream implements SmallIceCream{
	@Override
	public void makeIceCream() {
		System.out.println("制作一个小号香蕉口味冰淇淋");
	}
}

定义一个冰淇淋工厂接口+三个口味的冰淇淋工厂实现类

/**
 * 冰淇淋工厂接口,没有具体口味
 * @author xingyanan01-lhq
 */
public interface IceCreamFactory {
	public BigIceCream creamBigIceCream();
	public SmallIceCream creamSmallIceCream();
}
/**
 * 苹果冰淇淋工厂
 * @author xingyanan01-lhq
 */
public class AppleIceCreamFactory implements IceCreamFactory{
	@Override
	public BigIceCream creamBigIceCream() {
		return new BigAppleIceCream();
	}
	@Override
	public SmallIceCream creamSmallIceCream() {
		return new SmallAppleIceCream();
	}
}
/**
 * 橘子冰淇淋工厂
 * @author xingyanan01-lhq
 */
public class OrangeIceCreamFactory implements IceCreamFactory{
	@Override
	public BigIceCream creamBigIceCream() {
		return new BigOrangeIceCream();
	}
	@Override
	public SmallIceCream creamSmallIceCream() {
		return new SmallOrangeIceCream();
	}
}
/**
 * 香蕉冰淇淋工厂
 * @author xingyanan01-lhq
 */
public class BananaIceCreamFactory implements IceCreamFactory{
	@Override
	public BigIceCream creamBigIceCream() {
		return new BigBananaIceCream();
	}
	@Override
	public SmallIceCream creamSmallIceCream() {
		return new SmallBananaIceCream();
	}
}

具体实现:

/**
     * 客户端执行
     * @author xingyanan01-lhq
     */
    public static void main(String[] args) {
    	// 我去苹果口味冰淇淋工厂
    	AppleIceCreamFactory appleIceCreamFactory = new AppleIceCreamFactory();
    	// 要一个大冰淇淋
    	BigIceCream bigAppleIceCream = appleIceCreamFactory.creamBigIceCream();
    	bigAppleIceCream.makeIceCream();
    	// 要一个小冰淇淋
    	SmallIceCream smallAppleIceCream = appleIceCreamFactory.creamSmallIceCream();
    	smallAppleIceCream.makeIceCream();
    	// 我去橘子口味冰淇淋工厂
    	OrangeIceCreamFactory orangeIceCreamFactory = new OrangeIceCreamFactory();
    	// 要一个大冰淇淋
    	BigIceCream bigOrangeIceCream = orangeIceCreamFactory.creamBigIceCream();
    	bigOrangeIceCream.makeIceCream();
    	// 要一个小冰淇淋
    	SmallIceCream smallOrangeIceCream = orangeIceCreamFactory.creamSmallIceCream();
    	smallOrangeIceCream.makeIceCream();
    	// 我去香蕉口味冰淇淋工厂
    	BananaIceCreamFactory bananaIceCreamFactory = new BananaIceCreamFactory();
    	// 要一个大冰淇淋
    	BigIceCream bigBananaIceCream = bananaIceCreamFactory.creamBigIceCream();
    	bigBananaIceCream.makeIceCream();
    	// 要一个小冰淇淋
    	SmallIceCream smallBananaIceCream = bananaIceCreamFactory.creamSmallIceCream();
    	smallBananaIceCream.makeIceCream();
    }

【Java】设计模式(1)—工厂模式_第3张图片
可以看到,之所以叫抽象工厂,是因为和工厂方法相比,这里有多个抽象产品类存在(即大份的冰激凌和小份的冰激凌),每个抽象产品类可以派生出多个具体的产品,生产的是系列产品,其工厂接口相对于工厂方法模式而言,是有多个方法的,用来生产不同的抽象产品。

不过,我们也很容易看出,抽象工厂模式的弊端。比如现在,商场想要提供的是大、中、小三种系列产品,那么现在,需要改动的代码就有点多了。首先需要创建一个接口,用来生产中份的冰激凌,然后还要实现具体的类,还需要修改工厂接口,并修改具体的工厂类。

而且我们还可以看到,当业务逻辑复杂时,我们可以根据工厂类的定义,将很多个有逻辑关系的实现类归纳在一起,可能如果实现类只有10个8个,会觉得创建工厂没有什么必要,但是一旦实现类成百上千,这种工厂模式能很清晰的将实现类合并在一个工厂中。

5.我们为什么要用工厂模式?

回到之前的问题,我实体类很多,我每一个都能记得住,我直接new不香吗?为什么要用工厂模式来创建实体类?

如果你写了一个workUtil.java,里面放了很多很多很多你平时工作中需要用的业务处理方法,这个类有上万行代码。
这样代码可读性很差很差,而且每一次new这个对象需要做的初始化工作很多。

将很多工作装入一个方法中,相当于将很多鸡蛋放在一个篮子里,是很危险的,这也是有背于Java 面向对象的原则,面向对象的封装(Encapsulation)和分派(Delegation)告诉我们,尽量将长的代码分派“切割”成每段,将每段再“封装”起来(减少段和段之间耦合联系性),这样,就会将风险分散,以后如果需要修改,只要更改每段,不会再发生牵一动百的事情。

如果你根据你的工作需求将需要用的方法分类,创建一个workUtil接口,并根据业务场景分成了多个具体实现类(logWorkUtil、sqlWorkUtil、javaWorkUtil等等),
这样我们就能尽可能的将代码拆分,并且通过工厂模式来统一管理这些实现类快捷创建对应实现类,减少后期维护的代码修改量,也降低了耦合度。

你可能感兴趣的:(java,设计模式)