简述-工厂模式

工厂

事例:

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

抽象工厂和抽象产品

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


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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值