文章目录
一 、前言
工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。
工厂模式可以分为三类:
- 简单工厂模式(Simple Factory)
- 工厂方法模式(Factory Method)
- 抽象工厂模式(Abstract Factory)
这三种模式从上到下逐步抽象,并且更具一般性。
GOF 在《设计模式》一书中将工厂模式分为两类:工厂方法模式 与 抽象工厂模式。
简单工厂模式 不在23种设计模式之中。
所以有人认为 简单工厂模式 不属于23种GOF 设计模式之一,也有人将简单工厂模式 看为工厂方法模式的一种特例。
区别
工厂方法模式: | 抽象工厂模式: |
---|---|
一个抽象产品类,可以派生出多个具体产品类。 | 多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。 |
一个抽象工厂类,可以派生出多个具体工厂类。 | 一个抽象工厂类,可以派生出多个具体工厂类。 |
每个具体工厂类只能创建一个具体产品类的实例。 | 每个具体工厂类可以创建多个具体产品类的实例。 |
区别:
工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。
工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。
二、简单工厂模式
简单工厂模式, 又称 静态工厂方法模式 。从命名上就可以看出这个模式一定很简单。它存在的目的很简单:定义一个用于创建对象的接口。
先来看看它的组成:
-
抽象产品:它一般是具体产品继承的父类或者实现的接口。
-
具体产品:工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现。
-
工厂类:这是本模式的核心,含有一定的商业逻辑和判断逻辑,用来创建产品
2.1、优点
简单工厂模式的工厂类是整个模式的关键。其中包含了必要的逻辑判断,根据外部信息,决定究竟应该创建哪个具体类的对象。
通过使用简单工厂模式,用户无需了解对象如何创建的,只要传入必要信息就可以了。
2.2、缺点
工厂类集中了所有实例的创建逻辑,违背了高内聚责任分配原则。
随着系统中具体产品类不断增多,势必要不断修改工厂类,不易维护和扩展。同时,这也违背了开放封闭原则。
2.3、代码
2.3.1、产品接口
public abstract class Computer {
/**
* 产品的抽象方法,由具体的产品类去实现
*/
public abstract void start();
}
2.3.2、产品实现类
/**
* 华硕电脑
*/
public class AsusComputer extends Computer {
@Override
public void start() {
System.out.println("华硕电脑启动");
}
}
/**
* 惠普电脑
*/
public class HpComputer extends Computer{
@Override
public void start() {
System.out.println("惠普电脑启动");
}
}
/**
* 联想电脑
*/
public class LenovoComputer extends Computer{
@Override
public void start() {
System.out.println("联想电脑启动");
}
}
2.3.3、工厂类
public class ComputerFactory {
public static Computer createComputer(String type){
Computer mComputer=null;
switch (type) {
case "lenovo":
mComputer=new LenovoComputer();
break;
case "hp":
mComputer=new HpComputer();
break;
case "asus":
mComputer=new AsusComputer();
break;
}
return mComputer;
}
}
2.3.4、测试类
public class Main {
public static void main(String[] args) {
ComputerFactory.createComputer("lenovo").start();
ComputerFactory.createComputer("hp").start();
ComputerFactory.createComputer("asus").start();
}
}
联想电脑启动
惠普电脑启动
华硕电脑启动
三、工厂方法模式
工厂方法是在设计模式中常用的一种模式,它属于设计模式的创造类型模式,主要用来创建对象。
- 定义: 定义一个创建对象的接口,但让实现这个接口的类来决定要实例化那个类,工厂方法让类的实例化延迟到子类进行。
- 类型: 创建型
3.1、使用场景
- 创建对象需要大量重复的代码
- 客户端(应用层)不依赖与产品类实例如何被创建、实现细节
- 一个类通过其子类来指定创建那个对象
3.2、优点
- 用户只需要关心所需产品的对应工厂,无序关心创建细节
- 加入新的产品符合开闭原则,提高扩展性
3.3、缺点
- 类的个数容易过多,增加复杂度
- 增加了系统的抽象性和理解难度
3.4、代码
3.4.1、产品接口、工厂接口
/**
* 冰箱接口
*/
public interface IFridge {
//获取品牌名
String getBrandName();
//获取价格
double getPrice();
}
/**
* 冰箱工厂接口
*/
public interface IFridgeFactory {
IFridge getIRefrigerator();
}
3.4.2、产品实现类
/**
* 格力冰箱
*/
public class GeliFridge implements IFridge {
@Override
public String getBrandName() {
return "格力冰箱";
}
@Override
public double getPrice() {
return 3999;
}
}
/**
* 海尔冰箱
*/
public class HaierFridge implements IFridge {
@Override
public String getBrandName() {
return "海尔冰箱";
}
@Override
public double getPrice() {
return 5999;
}
}
/**
* 美的冰箱
*/
public class MeideFridge implements IFridge {
@Override
public String getBrandName() {
return "美的冰箱";
}
@Override
public double getPrice() {
return 2999;
}
}
3.4.3、工厂实现类
/**
* 格力冰箱工厂
*/
public class GeliFridgeFactory implements IFridgeFactory {
@Override
public IFridge getIRefrigerator() {
return new GeliFridge();
}
}
/**
* 海尔冰箱工厂
*/
public class HaierFridgeFactory implements IFridgeFactory {
@Override
public IFridge getIRefrigerator() {
return new HaierFridge();
}
}
/**
* 美的冰箱工厂
*/
public class MeideFridgeFactory implements IFridgeFactory {
@Override
public IFridge getIRefrigerator() {
return new MeideFridge();
}
}
3.4.4、测试类
/**
* 测试类
*/
public class Test {
public static void main(String[] args) {
IFridgeFactory haierFridgeFactory = new HaierFridgeFactory();
IFridgeFactory geliFridgeFactory = new GeliFridgeFactory();
IFridgeFactory mmeideFridgeFactory = new MeideFridgeFactory();
IFridge refrigerator = haierFridgeFactory.getIRefrigerator();
System.out.println("您购买了:" + refrigerator.getBrandName() + ",您需要支付:" + refrigerator.getPrice());
}
}
您购买了:海尔冰箱,您需要支付:5999.0
四、抽象工厂模式
有时候我们希望一个工厂可以生产多种产品,比如冰箱冰箱工厂中既可以生产冰箱又可以生产洗衣机、空调。很显然我们上篇文章中介绍的工厂方法是不能满足我们的需求,这个时候我们就需要用到抽象工厂。
- 定义:提供一个创建一系列相关或相互依赖的对象的接口
- 无序指定他们具体的类
- 类型:创建型
4.1、适用场景
- 客户端(应用层)不需要依赖与产品类实例
如何被创建、实现细节
等 - 强调一系列相关的产品对象(属于
同一产品族
)一起使用创建对象需要大量重复代码 - 提供一个产品类的库,所有的产品以
同样的接口出现
,从而使客户端不依赖于具体实现
4.2、优点
- 具体产品在应用层
代码隔离,无需关心创建细节
- 将一个系列的
产品族统一到一起创建
4.3、缺点
- 规定了所有可能被创建的产品集合,产品组种扩展新的产品比较困难,需要修改抽象工厂的接口
- 增加了系统的抽象性和理解难度
4.4、分析:
- 抽象方法是对工厂方法的进一步拓展
- 工厂工厂方法针对的是产品等级结构
- 抽象方法针对于的是产品族
- 加入我们想要创建海尔冰箱、海尔洗衣机、海尔空调;格力冰箱、格力洗衣机、格力空调;美的冰箱、美的洗衣机、美的空调;如果我们采用工厂方法的话,就需要9个工厂类,如果采用抽象工厂则需要3个类就可以完成。因此抽象工厂相比较工厂方法极大的减少了类的创建
4.5、代码
4.5.1、产品接口
/**
* 空调
*/
public interface IAirConditioner {
//品牌
String brand();
//制冷
void refrigeration();
//制热
void heating();
}
/**
* 洗衣机
*/
public interface IWasher {
String brand();
//洗涤
void washing();
}
/**
* 冰箱
*/
public interface IFridge {
String brand();
//储藏
void coldStorage();
//冷冻
void freeze();
}
4.5.2、产品实现类
海尔家电产品
/**
* 海尔空调
*/
class HaierAirConditioner implements IAirConditioner {
@Override
public String brand() {
return "海尔空调";
}
@Override
public void refrigeration() {
System.out.println("开启制冷模式");
}
@Override
public void heating() {
System.out.println("开启制热模式");
}
}
/**
* 海尔洗衣机
*/
class HaierWasher implements IWasher {
@Override
public String brand() {
return "海尔洗衣机";
}
@Override
public void washing() {
System.out.println("标准洗涤");
}
}
/**
* 海尔冰箱
*/
class HaierFridge implements IFridge {
@Override
public String brand() {
return "海尔冰箱";
}
@Override
public void coldStorage() {
System.out.println("冷藏室");
}
@Override
public void freeze() {
System.out.println("冷冻室");
}
}
格力空调家电产品
/**
* 格力空调
*/
class GeliAirConditioner implements IAirConditioner {
@Override
public String brand() {
return "格力空调";
}
@Override
public void refrigeration() {
System.out.println("开启制冷模式");
}
@Override
public void heating() {
System.out.println("开启制热模式");
}
}
/**
* 格力洗衣机
*/
class GeLiWasher implements IWasher {
@Override
public String brand() {
return "格力洗衣机";
}
@Override
public void washing() {
System.out.println("标准洗涤");
}
}
/**
* 格力洗衣机
*/
class GeliWasher implements IWasher {
@Override
public String brand() {
return "格力洗衣机";
}
@Override
public void washing() {
System.out.println("标准洗涤");
}
}
/**
* 格力冰箱
*/
class GeliFridge implements IFridge {
@Override
public String brand() {
return "格力冰箱";
}
@Override
public void coldStorage() {
System.out.println("冷藏室");
}
@Override
public void freeze() {
System.out.println("冷冻室");
}
}
4.5.3、抽象工厂接口
/**
* 家电工厂接口
*/
public interface IApplianceFactory {
//洗衣机
IWasher getWasher();
//空调
IAirConditioner getAirConditioner();
//冰箱
IFridge getFridge();
}
4.5.4、工厂实现类
/**
* 格力家电工厂
*/
public class GeliApplianceFactory implements IApplianceFactory {
@Override
public IWasher getWasher() {
return new GeliWasher();
}
@Override
public IAirConditioner getAirConditioner() {
return new GeliAirConditioner();
}
@Override
public IFridge getFridge() {
return new GeliFridge();
}
}
/**
* 海尔家电工厂
*/
public class HaierApplianceFactory implements IApplianceFactory {
@Override
public IWasher getWasher() {
return new HaierWasher();
}
@Override
public IAirConditioner getAirConditioner() {
return new HaierAirConditioner();
}
@Override
public IFridge getFridge() {
return new HaierFridge();
}
}
4.5.5、测试代码
public class Main {
public static void main(String[] args) {
// 洗衣机
IWasher washer = new GeliApplianceFactory().getWasher();
String washerBrand = washer.brand();
System.out.println("品牌:" + washerBrand);
washer.washing();
// 冰箱
IFridge fridge = new HaierApplianceFactory().getFridge();
String fridgeBrand = fridge.brand();
System.out.println("品牌:" + fridgeBrand);
fridge.coldStorage();
fridge.freeze();
// 空调
IAirConditioner airConditioner = new HaierApplianceFactory().getAirConditioner();
String airConditionerBrand = airConditioner.brand();
System.out.println("品牌:" + airConditionerBrand);
airConditioner.heating();
airConditioner.refrigeration();
}
}
运行结果:
品牌:格力洗衣机
标准洗涤
品牌:海尔冰箱
冷藏室
冷冻室
品牌:海尔空调
开启制热模式
开启制冷模式
转载: https://www.jianshu.com/p/4c7d0ee96094