Java设计模式——工厂模式
工厂模式(Factory Pattern
)属于创建型模式,它提供了一种创建对象的最佳方式。
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。术业有专攻就能很好的解释工厂模式,工厂模式就是专业生产商,我们拿来用就好了,不需要自己粗制乱遭,也不需要购买假冒伪劣产品,正规渠道拿货,质量有保障,安全,放心。
简单工厂模式
简单工厂模式不属于23种设计模式。他是由一个工厂实例来创建我们所需要的实例,适用于工厂类创建对象较少的场景。客户端只需要传入合适的参数就能获取所需对象,不需要关心对象的创建逻辑。
代码示例:
/**
* @description: 水果产品接口
* @author: lmc
* @create: 2019-03-19 21:28
**/
public interface IFruits {
/**
* 水果名称
*/
void getName();
/**
* 水果颜色
*/
void getColor();
/**
* 水果味道
*/
void getTaste();
}
/**
* @description: 苹果
* @author: lmc
* @create: 2019-03-19 21:33
**/
public class Apple implements IFruits {
@Override
public void getName() {
System.out.println(" 我是苹果,水果的一种");
}
@Override
public void getColor() {
System.out.println(" 苹果是红色的");
}
@Override
public void getTaste() {
System.out.println(" 苹果馋起来很甜很脆");
}
}
/**
* @description: 香蕉
* @author: lmc
* @create: 2019-03-19 21:33
**/
public class Banana implements IFruits {
@Override
public void getName() {
System.out.println(" 我是香蕉,水果的一种");
}
@Override
public void getColor() {
System.out.println(" 香蕉是黄色的");
}
@Override
public void getTaste() {
System.out.println(" 香蕉馋起来很甜很滑");
}
}
/**
* @description: 橙子
* @author: lmc
* @create: 2019-03-19 21:33
**/
public class Orange implements IFruits {
@Override
public void getName() {
System.out.println(" 我是橙子,水果的一种");
}
@Override
public void getColor() {
System.out.println(" 橙子是橙色的");
}
@Override
public void getTaste() {
System.out.println(" 橙子馋起来很甜水分足");
}
}
上面的代码 创建了一个水果接口,并且创建了三种水果分别实现了水果接口。
/**
* @description: 水果工厂
* @author: lmc
* @create: 2019-03-19 21:38
**/
public class FruitsFactory {
/**
* @description:
* @param fruitsName
* @return com.lmc.gp12380.pattern.factory.fruits.IFruits
* @date 2019/5/23 15:44
* @author lmc
*/
public IFruits product(String fruitsName){
if(null != fruitsName && fruitsName != ""){
System.out.println("客户需求的水果是"+fruitsName);
if("苹果".equals(fruitsName)){
System.out.println("水果工厂生产了苹果");
return new Apple();
}
if("橙子".equals(fruitsName)){
System.out.println("水果工厂生产了橙子");
return new Orange();
}
if("香蕉".equals(fruitsName)){
System.out.println("水果工厂生产了香蕉");
return new Banana();
}
return null;
}else{
return null;
}
}
}
简单工厂测试类
/**
* @description: 水果工厂测试类
* @author: lmc
* @create: 2019-03-19 21:50
**/
public class SimpleFactoryTest {
public static void main(String[] args) {
IFruits ifruits=null;
FruitsFactory ifruitsFactory =new FruitsFactory();
ifruits = ifruitsFactory.product("香蕉");
getFruitsName(ifruits,"香蕉");
ifruits = ifruitsFactory.product("苹果");
getFruitsName(ifruits,"苹果");
ifruits = ifruitsFactory.product("橙子");
getFruitsName(ifruits,"橙子");
ifruits = ifruitsFactory.product("草莓");
getFruitsName(ifruits,"草莓");
}
public static void getFruitsName(IFruits ifruits,String ifruitsName){
if(null != ifruits){
ifruits.getName();
}else{
if(null == ifruitsName || ifruitsName==""){
System.out.println("未指定水果让水果工厂生产");
}else{
System.out.println("水果工厂暂时无法生产"+ifruitsName);
}
}
}
}
测试结果
客户需求的水果是香蕉
水果工厂生产了香蕉
我是香蕉,水果的一种
客户需求的水果是苹果
水果工厂生产了苹果
我是苹果,水果的一种
客户需求的水果是橙子
水果工厂生产了橙子
我是橙子,水果的一种
客户需求的水果是草莓
水果工厂暂时无法生产草莓
上面的代码很简单,客户传入不同的参数,就能获取工厂对象能够生产的产品。业务需求中,工厂实例创建对象的业务逻辑往往是复杂的,运用简单工厂模式,客户端就不需要关心业务了,只要创建工厂对象,传入参数调用就能获取所需对象。
利:客户端调用简单,对于简单的业务逻辑清晰明了。
弊:
- 需要传参,容易出错。
- 传一个草莓参数,或者其他乱七八糟的参数,就得不到所需对象,出问题了
- 业务需要新的对象,需要更改工厂类,违背了开闭原则。
- 就像上面那样,我要一个草莓对象,工厂类暂时无法创建,需要修改代码。
- 工厂类的职责过重,不利于扩展复杂的产品结构(产品族和产品等级结构的概念后面会有说到)。
- 随着要生产的对象越来越多,工厂类变成了万能工厂了,违背了单一原则,不利于扩展和维护。
简单工厂类图:
工厂方法
工厂方法模式(FactoryMethodPattern
)是指定义一个创建对象的接口(工厂接口),但让实现这个
接口的类(工厂具体实现类)来决定实例化哪个类,工厂方法让类的实例化推迟到子类中进行。
现代化管理都是明确分工、专人干专事、团队协作。咱们的程序代码意思一样的。
来一个水果工厂接口
/**
* @description: 水果工厂接口
* @author: lmc
* @create: 2019-03-20 20:14
**/
public interface IFruitsFactory {
/**
* 工厂的生产方法
* @return IFruits
*/
IFruits product();
}
/**
* @description: 苹果工厂
* @author: lmc
* @create: 2019-03-20 20:19
**/
public class AppleFactory implements IFruitsFactory {
@Override
public IFruits product() {
System.out.println("苹果工厂只生产苹果");
return new Apple();
}
}
/**
* @description: 香蕉工厂
* @author: lmc
* @create: 2019-03-20 20:19
**/
public class BananaFactory implements IFruitsFactory {
@Override
public IFruits product() {
System.out.println("香蕉工厂只生产香蕉");
return new Banana();
}
}
/**
* @description: 橙子工厂
* @author: lmc
* @create: 2019-03-20 20:19
**/
public class OrangeFactory implements IFruitsFactory {
@Override
public IFruits product() {
System.out.println("橙子工厂只生产橙子");
return new Orange();
}
}
/**
* @description: 工厂方法测试
* @author: lmc
* @create: 2019-03-20 20:39
**/
public class MethodFactoryTest {
public static void main(String[] args) {
IFruitsFactory iFruitsFactory= new AppleFactory();
iFruitsFactory.product().getName();
iFruitsFactory = new BananaFactory();
iFruitsFactory.product().getName();
iFruitsFactory = new OrangeFactory();
iFruitsFactory.product().getName();
}
}
运行结果:
苹果工厂只生产苹果
我是苹果,水果的一种
香蕉工厂只生产香蕉
我是香蕉,水果的一种
橙子工厂只生产橙子
我是橙子,水果的一种
专人做专事,具体的对象只有具体的工厂创建。用户只有选择权,不需要传入参数。对象的实例化推迟到了工厂实现类创建。
利:
- 专人专事,遵循单一原则,子类工厂实现具体业务。让业务更清晰
- 遵循开闭原则,新增业务,只需要添加产品类和具体的产品工厂类就可以了,增加产品扩展性。
- 新增草莓产品,我只需要新增草莓类和草莓工厂就可以了。
弊:
- 类的个数容易过多,增加复杂度。
- 增加了系统的抽象性和理解难度。
工厂方法模式类图
抽象工厂模式
抽象工厂模式(Abstract Factory Pattern
)是指提供一个创建一系列相关或相互依赖对象的接口,无须指定他们具体的类。客户端(应用层)不依赖于产品类实例如何被创建、实现等细节,强调的是一系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量重复的代码。需要提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。
现在了解下上面提到的产品族和产品等级结构的概念。
产品族:属于一个产品工厂的所有产品。
产品等级结构:不等产品工厂生产的相同的同类产品。
现在水果工厂需求再次升级,之前又一个水果接口 IFruits
,那么我们再增加 水果果干接口IDriedFruits
、水果果汁接口 IJuice
/**
* @description: 水果干产品接口
* @author: lmc
* @create: 2019-03-19 21:28
**/
public interface IDriedFruits {
void getName();
void getColor();
void getTaste();
}
/**
* @description: 水果果汁品接口
* @author: lmc
* @create: 2019-03-19 21:28
**/
public interface IJuice {
void getName();
void getColor();
void getTaste();
}
现在我们有实现类 苹果汁 AppleJuice
、 苹果干 DriedApple
......
/**
* @description: 苹果干
* @author: lmc
* @create: 2019-03-19 21:33
**/
public class DriedApple implements IDriedFruits {
@Override
public void getName() {
System.out.println(" 我是苹果干,果干的一种");
}
@Override
public void getColor() {
System.out.println(" 苹果干大概也是白色的吧");
}
@Override
public void getTaste() {
System.out.println(" 苹果干没吃过,打个也是酸酸的吧");
}
}
/**
* @description: 苹果汁
* @author: lmc
* @create: 2019-03-19 21:33
**/
public class AppleJuice implements IJuice {
@Override
public void getName() {
System.out.println(" 我是苹果汁,果汁的一种");
}
@Override
public void getColor() {
System.out.println(" 苹果汁大概是白色的吧");
}
@Override
public void getTaste() {
System.out.println(" 苹果汁酸酸的");
}
}
/**
* @description: 香蕉干
* @author: lmc
* @create: 2019-05-23 23:06
**/
public class DriedBanana implements IDriedFruits {
@Override
public void getName() {
System.out.println(" 我是香蕉干,果干的一种");
}
@Override
public void getColor() {
System.out.println(" 香蕉干大概也是黄色的吧");
}
@Override
public void getTaste() {
System.out.println(" 香蕉干甜甜的");
}
}
/**
* @description: 香蕉汁
* @author: lmc
* @create: 2019-05-23 23:10
**/
public class BananaJuice implements IJuice {
@Override
public void getName() {
System.out.println(" 我是香蕉汁,果汁的一种");
}
@Override
public void getColor() {
System.out.println(" 香蕉汁大概是白色的吧");
}
@Override
public void getTaste() {
System.out.println(" 香蕉汁甜甜的");
}
}
/**
* @description: 橙子干
* @author: lmc
* @create: 2019-05-23 23:08
**/
public class DriedOrange implements IDriedFruits{
@Override
public void getName() {
System.out.println(" 我是橙子干,果干的一种");
}
@Override
public void getColor() {
System.out.println(" 橙子干大概也是橙黄色的吧");
}
@Override
public void getTaste() {
System.out.println(" 香蕉干没吃过 应该是甜甜的");
}
}
/**
* @description: 橙汁
* @author: lmc
* @create: 2019-05-23 23:12
**/
public class OrangeJuice implements IJuice {
@Override
public void getName() {
System.out.println(" 我是橙汁,果汁的一种");
}
@Override
public void getColor() {
System.out.println(" 橙汁是橙色的吧");
}
@Override
public void getTaste() {
System.out.println(" 橙汁汁酸酸甜甜的");
}
}
工厂类改造
抽象工厂接口,也可以改成抽象类
/**
* @description: 抽象工厂
* @author: lmc
* @create: 2019-03-21 21:59
**/
public interface IAbstractFruitsFactory {
/**
* @description: 水果生产
* @return com.lmc.gp12380.pattern.factory.fruits.IFruits
* @date 2019/5/24 8:33
* @author lmc
*/
IFruits productFruits();
/**
* @description: 果酱生产
* @return com.lmc.gp12380.pattern.factory.fruits.IDriedFruits
* @date 2019/5/24 8:34
* @author lmc
*/
IDriedFruits productIDriedFruits();
/**
* @description: 果汁生产
* @return com.lmc.gp12380.pattern.factory.fruits.IJuice
* @date 2019/5/24 8:34
* @author lmc
*/
IJuice productJuice();
}
/**
* @description: 苹果工厂
* @author: lmc
* @create: 2019-03-21 22:02
**/
public class AppleFactory implements IAbstractFruitsFactory {
/**
* @description:苹果生成
* @return com.lmc.gp12380.pattern.factory.fruits.IFruits
* @date 2019/5/23 15:14
* @author lmc
*/
@Override
public IFruits productFruits() {
return new Apple();
}
/**
* @description: 苹果酱生产
* @return com.lmc.gp12380.pattern.factory.fruits.IDriedFruits
* @date 2019/5/23 15:15
* @author lmc
*/
@Override
public IDriedFruits productIDriedFruits() {
return new DriedApple();
}
/**
* @description: 苹果汁生产
* @return com.lmc.gp12380.pattern.factory.fruits.IJuice
* @date 2019/5/23 15:15
* @author lmc
*/
@Override
public IJuice productJuice() {
return new AppleJuice();
}
}
/**
* @description: 香蕉工厂
* @author: lmc
* @create: 2019-05-24 08:35
**/
public class BananaFactory implements IAbstractFruitsFactory {
@Override
public IFruits productFruits() {
return new Banana();
}
@Override
public IDriedFruits productIDriedFruits() {
return new DriedBanana();
}
@Override
public IJuice productJuice() {
return new BananaJuice();
}
}
/**
* @description: 橙子工厂
* @author: lmc
* @create: 2019-05-24 08:27
**/
public class OrangeFactory implements IAbstractFruitsFactory {
@Override
public IFruits productFruits() {
return new Orange();
}
@Override
public IDriedFruits productIDriedFruits() {
return new DriedOrange();
}
@Override
public IJuice productJuice() {
return new OrangeJuice();
}
}
抽象工厂其实是一个产品族,具体的实现抽象工厂类生产的产品实例所产生同一产品类型,比如所有的水果是一个产品等级结构,所有的果酱也是一个产品等级结构,所有的果汁是一个产品等级结构。
/**
* @description: 抽象工厂方法测试
* @author: lmc
* @create: 2019-03-20 20:39
**/
public class AbstractFactoryTest {
public static void main(String[] args) {
AppleFactory appleFactory=new AppleFactory();
IFruits apple= appleFactory.productFruits();
apple.getName();
apple.getColor();
apple.getTaste();
IDriedFruits appleDriedFruits=appleFactory.productIDriedFruits();
appleDriedFruits.getColor();
appleDriedFruits.getName();
appleDriedFruits.getTaste();
IJuice appleJuice=appleFactory.productJuice();
appleJuice.getName();
appleJuice.getColor();
appleJuice.getTaste();
System.out.println("_________________________________________");
OrangeFactory orangeFactory=new OrangeFactory();
IFruits orange= orangeFactory.productFruits();
orange.getName();
orange.getColor();
orange.getTaste();
IDriedFruits orangeDriedFruits=orangeFactory.productIDriedFruits();
orangeDriedFruits.getColor();
orangeDriedFruits.getName();
orangeDriedFruits.getTaste();
IJuice orangeJuice=orangeFactory.productJuice();
orangeJuice.getName();
orangeJuice.getColor();
orangeJuice.getTaste();
System.out.println("_________________________________________");
BananaFactory bananaFactory=new BananaFactory();
IFruits banana= bananaFactory.productFruits();
banana.getName();
banana.getColor();
banana.getTaste();
IDriedFruits bananaDriedFruits=bananaFactory.productIDriedFruits();
bananaDriedFruits.getColor();
bananaDriedFruits.getName();
bananaDriedFruits.getTaste();
IJuice bananaJuice=appleFactory.productJuice();
bananaJuice.getName();
bananaJuice.getColor();
bananaJuice.getTaste();
}
}
测试结构
我是苹果,水果的一种
苹果干大概也是白色的吧
我是苹果干,果干的一种
苹果干没吃过,打个也是酸酸的吧
我是苹果汁,果汁的一种
苹果汁大概是白色的吧
苹果汁酸酸的
_________________________________________
我是橙子,水果的一种
橙子干大概也是橙黄色的吧
我是橙子干,果干的一种
橙子干没吃过 应该是酸酸甜甜的
我是橙汁,果汁的一种
橙汁是橙色的吧
橙汁汁酸酸甜甜的
_________________________________________
我是香蕉,水果的一种
香蕉是黄色的
香蕉馋起来很甜很滑
香蕉干大概也是黄色的吧
我是香蕉干,果干的一种
香蕉干甜甜的
我是香蕉汁,果汁的一种
香蕉汁大概是白色的吧
香蕉汁甜甜的
抽象工厂利弊
利:
- 适合复杂业务需求,清晰描述复杂关系。
- 专职专事,子类实现具体产品族业务。
弊:
- 违背开闭原则,新增产品族或者产品等级需要修改代码(产品迭代升级是有周期的)
- 增加系统的抽象性和理解难度。
抽象工厂类图
总结
工厂模式是一种面向对象程序封装,属于设计模式的创建型模式。客户端或者调用者需要的对象由工厂创建,不需要知道创建对象复杂的业务逻辑。简单工厂模式到工厂方法模式,再到抽象工厂模式。其实是一种社会进步的表现。
简单工厂就是一个小作坊,只要是工厂有这种产品都可以去生产。这就造成了管理不规范,维护困难。注定的简单工厂就是简单工厂,发展壮大不起来。当是呢方便,就好比你需要一箱牛奶,你去小超市就可以拿了,肯定不需要费九牛二虎之力去大草原找牛去挤奶吧。
工厂方法模式对应流水线生产企业。他们的产品比较少,管理规范,维护简单。这样的公司能够做大,出名,就好像那些只做单一产品的企业,比如服装工厂,塑料工厂。但是呢,产品单一,面临的竞争压力大,面临更复杂的业务束手无策,很容易被别人取而代之。对于新的产品,就要新建工程,新增流水线,投入成本太高。
抽象工厂模式:对应现代化产业链代工厂,生产、管理规范。强调的是产业链,一系列相互关联的产品。形成了一个产品生态。让用户不可或缺,绝对是世界级的大企业,比如华为,以及一些世界500强公司。他面临的是一个产业链的生产管理。抽象工厂模式封装的是复杂的产品关系业务。