设计模式-工厂方法模式
工厂方法模式
是为了弥补简单工厂模式
的不足并且继承它的优点而延生出的一种设计模式,它能更好的符合开闭原则的要求。
1 模式介绍
1.1 定义
工厂方法模式,又称工厂模式、多态工厂模式和虚拟构造器模式,通过定义工厂父类负责定义创建对象的公共接口,而子类则负责生成具体的对象。
1.2 解决的问题
发现简单工厂模式存在一系列问题:
工厂类集中了所有实例(产品)的创建逻辑,一旦这个工厂不能正常工作,整个系统都会受到影响;
违背“开放 - 关闭原则”,一旦添加新产品就不得不修改工厂类的逻辑,这样就会造成工厂逻辑过于复杂。
1.3 举个例子:
大众汽车公司想必大家都不陌生,它旗下也有不少汽车品牌。大众汽车公司就好比一个汽车工厂,负责生产和销售汽车。它可以为客户提供一个客户需要的汽车。但是,如果客户需要的汽车大众公司目前还没有,但是公司想要盈利,就必须为此而设计汽车,在这种情况下,大众公司就要新添加一种汽车,同时要修改公司内部的生产环境(也就是工厂类的代码)。这就是简单工厂模式的运行情况。简单而言,就是工厂类(汽车公司)什么都要干,要修改必须大动干戈。因而一定程度上违背了开闭原则。而工厂方法模式则不一样,大众汽车公司不在总公司生产汽车,而是成立分公司,收购别的公司,成立具有针对性的汽车工厂专门生产对应的汽车。若客户的大量需求得不到满足,则总公司就另外成立新的二级公司(新品牌汽车的工厂)生产汽车,从而在不修改具体工厂的情况下引进新的产品。正如大众集团的收购一样。以下为简单工厂模式和工厂方法模式的区别:
如果使用简单工厂
是这样的模式
如果使用工厂方法
是这样的模式
1.4 模式组成
组成(角色) | 关系 | 作用 |
---|---|---|
抽象产品(Product) | 具体产品的父类 | 描述具体产品的公共接口 |
具体产品(Concrete Product) | 抽象产品的子类;工厂类创建的目标类 | 描述生产的具体产品 |
抽象工厂(Creator) | 具体工厂的父类 | 描述具体工厂的公共接口 |
具体工厂(Concrete Creator) | 抽象工厂的子类;被外界调用 | 描述具体工厂;实现FactoryMethod工厂方法创建产品的实例 |
2 实例讲解:
手机专卖店Store
卖手机,目前Store
卖有两种手机,一个苹果手机,一个索尼手机,此时如果想从手机工厂进货“小米”手机,那么手机总工厂就必须修改内部实现
简单工厂模式由SimplePhoneFactory,集中获取不同的手机实例对象。
工厂方法模式由PhoneFactory的两个实现,分别获取不同的手机实例对象。
2.1 使用步骤
步骤1: 创建抽象产品类 ,定义具体产品的公共抽象接口;
public abstract class Phone {
/**
* 品牌
*/
protected String brand;
/**
* 操作系统
*/
protected String os;
/**
* 充电
*/
public abstract void charge();
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getOs() {
return os;
}
public void setOs(String os) {
this.os = os;
}
}
步骤2: 创建抽象工厂类,定义具体工厂的公共接口
public interface PhoneFactory {
Phone getPhone();
}
步骤3:创建具体工厂类(继承抽象工厂类),定义创建对应具体产品实例的方法;
// 苹果手机工厂
public class ApplePhoneFactory implements PhoneFactory {
@Override
public ApplePhone getPhone() {
ApplePhone applePhone = new ApplePhone();
applePhone.setBrand("Apple");
return applePhone;
}
}
// 索尼手机工厂
public class SonyPhoneFactory implements PhoneFactory {
@Override
public SonyPhone getPhone() {
SonyPhone sonyPhone = new SonyPhone();
sonyPhone.setBrand("Sony");
return sonyPhone;
}
}
// 更多其他手机工厂。。。
步骤4: 创建具体产品类(继承抽象产品类), 定义生产的具体产品;
// 苹果手机
public class ApplePhone extends Phone {
@Override
public void charge() {
System.out.println("普通充电");
}
}
// 索尼手机
public class SonyPhone extends Phone {
@Override
public void charge() {
System.out.println("快充");
}
}
步骤5:外界通过调用具体工厂类的方法,从而创建不同具体产品类的实例
// 手机专卖店
public class StoreB {
private PhoneFactory phoneFactory;
public StoreB(PhoneFactory phoneFactory) {
super();
this.phoneFactory = phoneFactory;
}
/**
* 补充手机
*/
public void supplyPhone() {
Phone phone = phoneFactory.getPhone();
// 补充手机逻辑...
System.out.println("补充" + phone.getBrand() + "手机完成");
}
public static void main(String[] args) {
StoreB storeB = new StoreB(new SonyPhoneFactory());
storeB.supplyPhone();
}
}
结果:
补充Sony手机完成
优点:
- 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程;
- 在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则;
缺点:
- 每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度
总结:工厂模式可以说是简单工厂模式的进一步抽象和拓展,在保留了简单工厂的封装优点的同时,让扩展变得简单,让继承变得可行,增加了多态性的体现。
源码:设计模式
其他设计模式介绍:
更多精彩内容:mrxccc