应用最广泛的工厂模式

来源:互联网 发布:linux 怎么引导win 7 编辑:程序博客网 时间:2024/05/21 18:36

工厂

事例:

某公司下有多条生产线,都是生产鸭脖。但鸭脖有酱香的,有麻辣的,有五香的,有原味的。每条生产线生产一种鸭脖,而鸭脖又对应不同味道即不同商标。对于忙碌的领导来说,他需要知道所有生产线吗和所有鸭脖吗?那样的话要记录的事也太多了,越来越多的生产线和鸭脖味道就会越来越复杂。对应在程序中也是如此,领导只需要关心有生产线生产鸭脖,鸭脖有味道就可以了。用得最多的模式,工厂模式来表述上面事例。

抽象工厂和抽象产品

基于面向对象的思想,首先定义一个生产线接口,它有一个实现生产鸭脖的方法。再定义一个鸭脖接口,它有一个味道的方法。

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是饮料,其都是工厂生产产品,而产品具体实现交由产品自己实现。在项目中是一个可替换模块(工厂),对应行为也可替换(产品),但实现不同,将组成部分抽象。

工厂模式是完全符合设计原则的,依赖与抽象的架构,将具体操作交由对应的子类完成,有非常好的扩展性。很多一些使扩展性好的设计模式,比如策略,状态等也都能看到工厂模式的影子。工厂模式不愧为应用最广泛的设计模式

原创粉丝点击