工厂模式,实际上也会根据业务情景不同会有不同的实现方式。一般分为3种。简单工厂,工厂模式和抽象工厂。顾名思义,这三种从简单到抽象,名称越来越高大上,实现方式肯定是越来越复杂
结论1:三种工厂的实现越来越复杂
简单工厂
public class Factory
{
// 定义产品编号
public int prodNo;
// 构造工厂时告知工厂产品标识
public Factory(int prodNo)
{
this.prodNo = prodNo;
}
public IProduct GetProduct()
{
// 根据产品标识生产产品
switch (prodNo)
{
case prodNo1:
return new ProductA();
break;
case prodNo2:
return new ProductB();
break;
default:
...
}
}
}
// 产品A
class ProductA implements IProduct
{
//产品属性
//......
}
//产品B
class ProductB implements IProduct
{
//产品属性
//......
}
//产品接口
public interface IProduct
{
//产品方法
//......
}
简单工厂的问题就在于swich case(或者if else)。每当新增一种产品时,你都需要去维护工厂中的判断语句,造成该工厂类不断增长,各种判断挤在一起,给扩展和维护带来麻烦。产品和工厂没有实现完全解耦,绑定在一起
结论2:简单工厂通过构造时传入的标识来生产产品,不同产品都在同一个工厂中生产,这种判断会随着产品的增加而增加,给扩展和维护带来麻烦
工厂模式
// 工厂接口
interface IFactory
{
IProduct GetProduct();
}
// A工厂类
class FactoryA implements IFactory
{
IProduct productA;
public FactoryA()
{
this.productA = new ProductA();
}
public IProduct GetProduct() //A工厂生产A产品
{
return this.productA;
}
}
//B工厂类
class FactoryB implements IFactory
{
IProduct productB;
public FactoryB()
{
this.productB = new ProductB();
}
public IProduct GetProduct() //B工厂生产B产品
{
return this.productB;
}
}
//产品接口
interface IProduct
{
//产品方法
//......
}
//产品A
class ProductA implements IProduct
{
//产品属性
//......
}
//产品B
class ProductB implements IProduct
{
//产品属性
//......
}
在工厂模式中,已经将工厂类分开,不再将所有产品在同一工厂中生产,解决了简单工厂中不断增加的switch case的问题。如再新增一个C产品,那么只需写一个C工厂和C产品,在调用时用C工厂生产C产品即可,A和B工厂和产品完全不受影响
结论3:工厂模式无法解决产品族和产品等级结构的问题
抽象工厂
实现不同的产品族,并且实现产品等级结构
// 工厂接口,即抽象工厂
interface IFactory
{
IFridge CreateFridge();
IAirCondition CreateAirCondition();
}
// 三星的工厂,生产三星的产品族
class SamsungFactory implements IFactory
{
public IAirCondition CreateAirCondition()
{
// 三星的工厂生产三星的空调
return new SamsungAirCondition();
}
public IFridge CreateFridge()
{
// 三星的工厂生产三星的冰箱
return new SamsungFridge();
}
}
// 格力的工厂,生产格力的产品族
class GreeFactry implements IFactory
{
public IAirCondition CreateAirCondition()
{
// 格力的工厂生产格力的空调
return new GreeAirCondition();
}
public IFridge CreateFridge()
{
// 格力的工厂生产格力的冰箱
return new GreeFridge();
}
}
// 冰箱产品接口
interface IFridge
{
// 冰箱产品接口
// 冰箱的action
}
// 空调接口
interface IAirCondition
{
// 空调产品接口
// 空调的action
}
// 三星的冰箱
public class SamsungFridge implements IFridge
{
// 三星冰箱的action和property
}
// 格力的冰箱
public class GreeFridge : IFridge
{
// 格力冰箱的action和property
}
// 三星的空调
public class SamsungAirCondition implements IAirCondition
{
// 三星空调的action和property
}
// 格力的空调
public class GreeAirCondition implements IAirCondition
{
/ /格力空调的action和property
}
在工厂模式中,一个工厂生产一个产品,所有的具体产品是由同一个抽象产品派生的,不存在产品等级结构和产品族的概念;而在抽象工厂中,同一个等级的产品是派生于一个抽象产品(即产品接口),一个抽象工厂派生不同的具体工厂,每个具体工厂生产自己的产品族(包含不同产品等级)
结论4:工厂模式中,一个工厂生产一个产品,所有产品派生于同一个抽象产品(或产品接口);而抽象工厂模式中,一个工厂生产多个产品,它们是一个产品族,不同的产品族的产品派生于不同的抽象产品(或产品接口)
三种工厂模式关键点
三种工厂的实现是越来越复杂的
简单工厂通过构造时传入的标识来生产产品,不同产品都在同一个工厂中生产,这种判断会随着产品的增加而增加,给扩展和维护带来麻烦
工厂模式无法解决产品族和产品等级结构的问题
抽象工厂模式中,一个工厂生产多个产品,它们是一个产品族,不同的产品族的产品派生于不同的抽象产品(或产品接口)
工厂模式问答
在上面的代码中,都使用了接口来表达抽象工厂或者抽象产品,那么可以用抽象类吗?有何区别?
从功能上说,完全可以,甚至可以用接口来定义行为,用抽象类来抽象属性。抽象类更加偏向于属性的抽象,而用接口更加偏向行为的规范与统一。使用接口有更好的可扩展性和可维护性,更加灵活实现松散耦合,所以编程原则中有一条是针对接口编程而不是针对类编程
到底何时应该用工厂模式
根据具体业务需求。不要认为简单工厂是用switch case就觉得一无是处,也不要觉得抽象工厂比较高大上就到处套。我们使用设计模式是为了解决问题而不是炫技,所以根据三种工厂模式的特质,以及对未来扩展的预期,来确定使用哪种工厂模式
说说你在项目中工厂模式的应用
一个旅游产品的B2B网站,根据不同类型的业务形态,产品也是不同的,有国内跟团,出境跟团,国内自由行,出境自由行,邮轮五种产品,并且后面可能还会有门票,酒店,机票等等产品,其中有些联系也有些区别