工厂
事例:
某公司下有多条生产线,都是生产鸭脖。但鸭脖有酱香的,有麻辣的,有五香的,有原味的。每条生产线生产一种鸭脖,而鸭脖又对应不同味道即不同商标。对于忙碌的领导来说,他需要知道所有生产线吗和所有鸭脖吗?那样的话要记录的事也太多了,越来越多的生产线和鸭脖味道就会越来越复杂。对应在程序中也是如此,领导只需要关心有生产线生产鸭脖,鸭脖有味道就可以了。用得最多的模式,工厂模式来表述上面事例。
抽象工厂和抽象产品
基于面向对象的思想,首先定义一个生产线接口,它有一个实现生产鸭脖的方法。再定义一个鸭脖接口,它有一个味道的方法。
public interface IProductLineFactory{
IDuckNeck createDuckNeck();
}
public interface IDuckNeck{
void taste();
}
实际工厂和实际产品
我们假设要找产原味鸭脖的生产线生产原味鸭脖。
public class NormalProductLineFactory implements IProductLineFactory{
@Override
public IDuckNeck createDuckNeck(){
return new NormalTasteDuckNeck();
}
}
public class NormalTasteDuckNeck implements IDuckNeck {
@Override
public void taste(){
System.out.printls("这里是原味鸭脖哦");
}
}
然后我们想要获取看看鸭脖味道:
public class Test{
public static void main(String[] args){
IProductLineFactory factory=new NormalProductLineFactory();
IDuckNeck duckneck=factory.createDuckNeck();
duckneck.taste();
}
}
这里几个角色也很简单,主要四大模块:
- 抽象工厂:这就是工厂方法的核心
- 具体工厂:实现具体的业务逻辑,生产具体的产品。
- 抽象产品:产品的父类,描述产品该有的行为。
- 具体产品:抽象产品具体产品的对象,实现具体行为。
要找另外的生产线生产另外味道的鸭脖,也可以轻而易举的就执行了。对于领导只需要知道生产线生产鸭脖,鸭脖有自己的味道就可以了。如果想得到麻辣味鸭脖,只需要更改工厂实现逻辑即可,返回麻辣味鸭脖就可以了。
当然这种方式,我们需要创建更多的工厂具体类,所以也是挺麻烦的,通常我们可以通过自己喜欢的方式来不重复创建工厂类:
实际使用工厂方式
反射创建
public interface IProductLineFactory{
/**
* 抽象工厂方法
* @param clz 产品对象类型
* @return 具体产品对象
*/
<T extends IDuckNeck> T createDuckNeck(Class<T> clz);
}
对于具体工厂类,我们可以通过反射获取类的实例:
public class ConcreteFactory implements IProductLineFactory{
public <T extends IDuckNeck> T createDuckNeck(Class<T> clz){
IDuckNeck duckneck;
try{
duckneck=(IDuckNeck)Class.forName(clz.getName()).newInstance();
}catch(Exception e){
}
return duckneck;
}
}
再来看下测试:
public class Test{
public static void main(String[] args){
IProductLineFactory factory=new ConcreteFactory();
IDuckNeck duckneck=factory.createDuckNeck(NormalTasteDuckNeck.class);
duckneck.taste();
}
}
这是一种方式,通过反射就不用反复创建具体工厂了,当然反射效率稍微要低一点,所以还是可以有其他方式实现。
实现方式看具体业务逻辑需求,如果工厂只有一个,可以直接用静态工厂,来去掉抽象工厂类。
静态工厂:
public class ConcreteFactory{
public static IDuckNeck createDuckNeck(){
return new NormalTasteDuckNeck();
}
}
静态工厂是工厂方式的一种弱化,就直接简化掉了抽象工厂类,如果产品类型不是很多,还可以在抽象工厂类中加入Type类型,来做一个switch取出直接产品类型。
抽象工厂
事例
夏天来了,我们都爱喝饮料,比如某快线和某矿泉水。某快线由饮料部分是乳白色。而矿泉水是透明色,某快线盖子是橙色,矿泉水盖子是白色。身体部分均由软塑料瓶组成。
那么换到我们代码世界中来,不就对应了可替换模块不同实现和实现下组成部分的不同,将组成部分抽象,将每一个组成部分看作一个产品。
抽象工厂
- 先定义一个抽象饮料:
public abstract class DrinkFactory{
/**
* 生产液体
* return 液体部分
*/
public abstract ILiquid createLiquid();
/**
* 生产盖子
* return 盖子部分
*/
public abstract ICap createCap();
/**
* 生产瓶子
* 因为两个产品瓶子一样,所以可以Up Method 到父类中,如果子类需要改变则自己重写就好
*/
protect void createBottle(){
System.out.println("瓶身是熟料瓶身");
}
}
- 液体相关类
public interface ILiquid{
void liquid();
}
public class TransparencyLiquid implements ILiquid{
@Override
public void liquid(){
System.out.println("透明液体");
}
}
public class LacteLiquid implements ILiquid{
@Override
public void liquid(){
System.out.println("乳白色液体");
}
}
- 盖子相关类
public interface ICap{
void cap();
}
public class OrangeCap implements ICap{
@Override
public void cap(){
System.out.println("橙色盖子");
}
}
public class WhiteCap implements ICap{
@Override
public void cap(){
System.out.println("白色盖子");
}
}
声明完了之后,具体工厂就出来了:
- 具体工厂类:
public class XXQX extends DrinkFactory{
/**
* 生产液体
* return 液体部分
*/
@Override
public ILiquid createLiquid(){
return new LacteLiquid();
}
/**
* 生产盖子
* return 盖子部分
*/
@Override
public ICap createCap(){
return new OrangeCap();
}
}
public class XXMineralWater extends DrinkFactory{
/**
* 生产液体
* return 液体部分
*/
@Override
public ILiquid createLiquid(){
return new TransparencyLiquid();
}
/**
* 生产盖子
* return 盖子部分
*/
@Override
public ICap createCap(){
return new WhiteCap();
}
}
测试:
public class Test{
public static void main(String[] args){
DrinkFactory factoryMineralWater=new XXMineralWater();
factoryMineralWater.createLiquid().liquid();
factoryMineralWater.createCap().cap();
factoryMineralWater.createBottle();
System.out.println("-------");
DrinkFactory factoryQX=new XXQX();
factoryQX.createLiquid().liquid();
factoryQX.createCap().cap();
factoryQX.createBottle();
}
}
就这样就把一个饮料给拆分了,组成部分也为产品,我们也可以抽象出来,当其他饮料需要用到的时候可以直接使用,扩展性更好了。
这里用的抽象类,有一个好处就是提升了公共部分,重构的时候,往往会用到此方式,UP Method。就像这里的瓶身
总结
例子1是鸭脖,例子2是饮料,其都是工厂生产产品,而产品具体实现交由产品自己实现。在项目中是一个可替换模块(工厂),对应行为也可替换(产品),但实现不同,将组成部分抽象。
工厂模式是完全符合设计原则的,依赖与抽象的架构,将具体操作交由对应的子类完成,有非常好的扩展性。很多一些使扩展性好的设计模式,比如策略,状态等也都能看到工厂模式的影子。工厂模式不愧为应用最广泛的设计模式