常见的设计模式:工厂模式

  设计模式,是一个在面试当中很常听到的词,是一些大佬们在编程的过程当中,总结出来的应用于不同场景的代码编写模版,那么今天我们就来学习一下一个最基础的设计模式——工厂模式。

  工厂模式属于创建型的设计模式,顾名思义,所谓的工厂,就是专门用来生产的,那么在编程当中,工厂模式的工厂,就是专门为我们生产 “实例” 的。在平常的使用当中,比如A类当中的某个方法需要使用到B类,则需要A类在自己的方法当中对B类进行new出一个实例,之后再进行应用,而这时候C类如果也需要在自己的方法当中使用B类,则也需要在自己的方法当中对B类实例化,这时候如果将B类实例化这个工作交与D类去做,而A类和C类都直接从D类去获取B类的实例直接进行使用,那么这时候的D类,就是我们所说的工厂类。也许你会问,不就是一个new操作嘛,何必需要再弄一个D类来new,不是更麻烦吗?如果我们约定,对B类进行实例化后,需要对B类当中的100种变量进行重新赋值(这里只是打个比方,实际上不会有那么变态的场景,之所以这么说,是为了表述B的实例化变为了一个复杂的过程)才能对B类的实例进行使用呢?这时候如果不引用D类(工厂类)那么需要在A类当中的方法写101行代码,在C类当中的方法也写相同的101行代码,这就显得很复杂了,所以这时候我们的工厂类就登场了。

  那么接下来我们先介绍工厂模式当中的最简单的形式——静态工厂模式(简单工厂模式)

1.简单工厂模式:在静态工厂模式当中有这么几个概念:

1)工厂类:即要生产产品(实例)的类;

2)抽象产品:它一般是具体产品继承的父类或者实现的接口。 

3)具体产品:工厂类所创建的对象就是此角色的实例。在Java中由一个具体类实现。 

  首先我们来设定这么一个背景:想必大家对本田车(Honda车)有一点的了解,那么假定现在有两种型号的本田车,CRV和URV,用户可能会对这两种车进行使用。那么在这里例子当中呢,我们的工厂类就是本田车厂,抽象产品为Honda车,而具体产品为:CRV和URV,接下来我们看看代码。

public interface Honda {   //抽象产品

    public void CarVersion();
    
}
//具体产品
public class CRV implements Honda {
    @Override
    public void CarVersion() {
        System.out.println("this is CRV");
    }
}

class URV implements Honda
{
    @Override
    public void CarVersion() {
        System.out.println("this is URV");
    }
}
//工厂类
public class HondaFactory {

    public Honda createTheCar(String version)
    {
         switch (version) {  
            case "CRV":  
                return new CRV();  
      
            case "URV":  
                return new URV();  
      
            default:  
                break;  
            }  
        return null;
    }
    
}
//客户类、
public class Customer {

    public static void main(String[] args) {
        HondaFactory f=new HondaFactory();
        Honda crv=f.createTheCar("CRV");
        crv.CarVersion();
        Honda urv=f.createTheCar("URV");
        urv.CarVersion();
    }

}
//运行结果
this is CRV
this is URV

可以看到,客户根本不关心这两种车是怎么实现的,客户类所做的操作就是到工厂类提 “车”,这就是简单的工厂模式,那么这种简单的工厂模式会有一个很大的局限性,就是如果我们再加一种车型叫做XRV,那么我们就需要对工厂类进行改造,添加switch当中的case,这是很不方便的,为了解决这个问题,又提出了工厂方法模式。

2.工厂方法模式

  工厂方法模式比起简单的工厂模式来说,不同点就在于它将工厂类也分为了抽象工厂和具体的工厂,抽象工厂呢,它是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。 在这个例子当中,我们的抽象工厂就是Honda的造车厂,而具体的工厂,就分化出来了CRV的造车厂,URV的造车厂,用这样的方法,在添加一种车型叫XRV的话,我们只需要添加一个具体的XRV的造车厂就可以,而不需要修改其他任何已有的代码。接下来看具体的代码:

//抽象产品
public interface HondaCar {

    public void CarVersion();
    
}
//具体产品
public class CRV implements HondaCar {
    @Override
    public void CarVersion() {
        System.out.println("this is CRV");
    }
}

class URV implements HondaCar
{
    @Override
    public void CarVersion() {
        System.out.println("this is URV");
    }
}

class XRV implements HondaCar
{
    @Override
    public void CarVersion() {
        System.out.println("this is XRV");
    }
}
//抽象工厂
public interface HondaFactory {

    HondaCar buildTheCar();
}
//具体工厂
public class CRVFactory implements HondaFactory {

    @Override
    public HondaCar buildTheCar() {
        // TODO Auto-generated method stub
        return new CRV();
    }
}

class URVFactory implements HondaFactory
{
    @Override
    public HondaCar buildTheCar() {
        // TODO Auto-generated method stub
        return new URV();
    }    
}

class XRVFactory implements HondaFactory
{
    @Override
    public HondaCar buildTheCar() {
        // TODO Auto-generated method stub
        return new XRV();
    }    
}
//客户
public class Customer {

    public static void main(String[] args) {
        HondaFactory c=new CRVFactory();
        HondaCar crv=c.buildTheCar();
        crv.CarVersion();

        HondaFactory u=new URVFactory();
        HondaCar urv=u.buildTheCar();
        urv.CarVersion();
        
        HondaFactory x=new XRVFactory();
        HondaCar xrv=x.buildTheCar();
        xrv.CarVersion();
    }

}
//运行结果
this is CRV
this is URV
this is XRV

通过工厂方法模式,我们看似完美的解决了添加车型的问题,但是,如果由于车型的不同,导致车上的配件的档次也不相同,比如说:在URV上,我们需要装高级的空调和座椅,而CRV上我们可能就装中级的空调和座椅,那么这时候我们就需要采用抽象工厂的方法的形式来解决。这里我们来举个例子来说明抽象工厂和工厂方法的区别

我们依然拿生产汽车的例子来说明他们之间的区别。

        在上面的类图中,两厢车和三厢车称为两个不同的等级结构;而2.0排量车和2.4排量车则称为两个不同的产品族。再具体一点,2.0排量两厢车和2.4排量两厢车属于同一个等级结构,2.0排量三厢车和2.4排量三厢车属于另一个等级结构;而2.0排量两厢车和2.0排量三厢车属于同一个产品族,2.4排量两厢车和2.4排量三厢车属于另一个产品族。

        明白了等级结构和产品族的概念,就理解工厂方法模式和抽象工厂模式的区别了,如果工厂的产品全部属于同一个等级结构,则属于工厂方法模式;如果工厂的产品来自多个等级结构,则属于抽象工厂模式。在本例中,如果一个工厂模式提供2.0排量两厢车和2.4排量两厢车,那么他属于工厂方法模式;如果一个工厂模式是提供2.4排量两厢车和2.4排量三厢车两个产品,那么这个工厂模式就是抽象工厂模式,因为他提供的产品是分属两个不同的等级结构。当然,如果一个工厂提供全部四种车型的产品,因为产品分属两个等级结构,他当然也属于抽象工厂模式了。(参考:http://blog.csdn.net/zhengzhb/article/details/7359385/)

明白了之后我们再回到我们的本田车的例子当中,接下来我们来看看本田车的抽象工厂去实现CRV使用中级座椅和空调,而URV使用高级座椅和空调的代码:

//抽象产品接口
public interface HondaCar {

    public void CarVersion();
    
}

public interface AirCondition {

    void AirconditionVersion();
    
}

public interface Seat {

    void SeatLevel();
}
//具体产品类
class highAC implements AirCondition {
    @Override
    public void AirconditionVersion() {
        System.out.println("this is high AC");
    }
}

 class MiddleAC implements AirCondition {
        @Override
        public void AirconditionVersion() {
            System.out.println("this is middle AC");
        }
}

class HighSeat implements Seat {
    @Override
    public void SeatLevel() {
        System.out.println("this is the High seat");
    }
}

class MiddleSeat implements Seat {
    @Override
    public void SeatLevel() {
        System.out.println("this is the Middle seat");
    }
}

class CRV implements HondaCar {
    @Override
    public void CarVersion() {
        System.out.println("this is CRV");
    }
}

class URV implements HondaCar
{
    @Override
    public void CarVersion() {
        System.out.println("this is URV");
    }
}

class XRV implements HondaCar
{
    @Override
    public void CarVersion() {
        System.out.println("this is XRV");
    }
}
//抽象工厂
public interface HondaFactory {

    HondaCar buildTheCar();
    AirCondition getTheAirCondition();
    Seat getTheSeat();
}
//具体工厂
public class CRVFactory implements HondaFactory {

    @Override
    public HondaCar buildTheCar() {
        // TODO Auto-generated method stub
        return new CRV();
    }

    @Override
    public AirCondition getTheAirCondition() {
        // TODO Auto-generated method stub
        return new MiddleAC();
    }

    @Override
    public Seat getTheSeat() {
        // TODO Auto-generated method stub
        return new MiddleSeat();
    }
}

class URVFactory implements HondaFactory
{
    @Override
    public HondaCar buildTheCar() {
        // TODO Auto-generated method stub
        return new URV();
    }

    @Override
    public AirCondition getTheAirCondition() {
        // TODO Auto-generated method stub
        return new highAC();
    }

    @Override
    public Seat getTheSeat() {
        // TODO Auto-generated method stub
        return new HighSeat();
    }    
}
//客户
public class Customer {

    public static void main(String[] args) {
        HondaFactory c=new CRVFactory();
        HondaCar crv=c.buildTheCar();
        crv.CarVersion();
        

        HondaFactory u=new URVFactory();
        HondaCar urv=u.buildTheCar();
        urv.CarVersion();
        

    }

}

到此,工厂模式就介绍完毕了。

总结一下:

简单工厂模式:对于增加新产品无能为力

工厂方法模式:通过新增实现具体工厂类的方式,可以增加新产品。

抽象工厂模式:对增加新产品无能为力,但是可以增加新产品族

本文参考了:http://blog.csdn.net/jason0539/article/details/23020989#comments   当中的博客,并且再加之自己的理解和话进行重新表述,也许引用的例子会大部分类似,还请谅解。

 

转载于:https://www.cnblogs.com/WellHold/p/7458206.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值