设计模式之工厂模式(简单工厂模式,工厂方法模式,抽象工厂模式)

简单工厂模式:

  角色: 抽象产品类 具体产品类 产品工厂类

  定义:将被使用方的创建过程封装到一个类中,这样就在使用方和被使用方之间做了一个缓冲,也就是使用方和被使用方做了一个解耦,提高了软件的可扩展性和可维护性和可复用性.

现在有一个手机抽象类

public abstract class Phone {

   public abstract void makePhone();
}

两个实现类

public class XiaoMi extends Phone {

    @Override
    public void makePhone() {
        System.out.println("制造出了小米手机");
    }
}
public class HWPhone extends Phone {

    @Override
    public void makePhone() {
        System.out.println("制造出了华为手机");
    }
}

为了不让调用方直接去调用这两个类去创建实例.我们提供一个工厂类的静态方法去创建不同品牌手机的实例对象

public class PhoneFactory {

    public static Phone createPhone(Integer type){
        Phone phone=null;
       if(1==type){
           phone = new XiaoMi();
       }else if(type==2){
           phone = new HWPhone();
       }
        return phone;
    }

}

接下来一个客户端调用工厂类来创建

public class Consumer {

    public static void main(String[] args) {
        PhoneFactory.createPhone(1).makePhone();
        PhoneFactory.createPhone(2).makePhone();
    }

}

输出结果:

 

 

 这样我们就在使用和被使用方之间做了一层缓冲,避免了使用方和被使用方耦合性过高.当我们需要再次创建一个新品牌的手机,我们还是需要在工厂类修改代码.

 

所以简单工厂的使用场景:

  具体类十分确定且固定的一类产品的创建,这样不至于频繁的修改工厂类的代码去实现扩展.而为了弥补简单工厂模式的缺点,再次基础上我们就要延伸下面的模式\

 

工厂方法模式:

  角色:抽象产品类 具体产品类 抽象工厂类(只有一个接口方法生产产品) 具体工厂类

  定义:将简单工厂的创建对象的方法写成一个抽象方法,也就是在工厂类或者接口中不知道如何创建该对象,创建具体对象交给工厂类的子类或者实现类去做.

我们首先改造之前的工厂类为抽象接口

public interface PhoneFactory {
    
   Phone createPhone();
   

}

我们为每一个手机品牌实现一个对应的工厂类

public class HWFactory implements PhoneFactory {

    @Override
    public Phone createPhone() {
      new HWPhone();
    }
}
public class XiaoMiFactory implements PhoneFactory {

    @Override
    public Phone createPhone() {
     return new XiaoMi();
    }
}

 然后我们再次通过消费者调用

public class Consumer {

    public static void main(String[] args) {
        XiaoMiFactory xiaoMiFactory = new XiaoMiFactory();
        xiaoMiFactory.createPhone().makePhone();
        HWFactory hwFactory = new HWFactory();
        hwFactory.createPhone().makePhone();
    }

}

输出结果:

 

 

 我们在之前简单工厂的基础上,把工厂类页向上抽象了一层,这样我们需要什么工厂就去实现工厂抽象接口,获得不同的工厂,我们的工厂方法相比之前的静态方法工厂类

  优点:让扩展变得简单,并且每个工厂创建不同的产品,符合单一职能原则

  缺点:当新增加一个产品,需要创建对应的产品工厂类,一个工厂只能创建一个产品.

 

抽象工厂模式

   角色:抽象产品类 具体产品类 抽象工厂类(多个生产产品方法,一个产品族) 具体工厂类

原有基础上,我们之前的抽象工厂接口只有一个创建产品的方法,在抽象工厂模式里面,我们的抽象工厂将有多个创建同一族产品的方法,架设现在我们有需要生产手机壳

手机壳抽象类

public abstract class PhoneShell {
    
     abstract void makePhoneShell();
}

手机壳实现类

public class XiaoMiShell extends PhoneShell {


    @Override
    void makePhoneShell() {
        System.out.println("小米手机壳");
    }
}
public class HWShell extends PhoneShell {

    @Override
    void makePhoneShell() {
        System.out.println("华为手机壳");
    }
}

现在我们把之前的抽象工厂类接口增加一个抽象方法

public interface PhoneFactory {

   Phone createPhone();

   PhoneShell createShell();


}

抽象工厂实现类

public class XiaoMiFactory implements PhoneFactory {

    @Override
    public Phone createPhone() {
       return new XiaoMi();
    }

    @Override
    public PhoneShell createShell() {
        return new XiaoMiShell();
    }
} 
public class HWFactory implements PhoneFactory {

    @Override
    public Phone createPhone() {
      return new HWPhone();
    }

    @Override
    public PhoneShell createShell() {
        return new HWShell();
    }
}

调用方

public class Consumer {

    public static void main(String[] args) {
        XiaoMiFactory xiaoMiFactory = new XiaoMiFactory();
        xiaoMiFactory.createPhone().makePhone();
        xiaoMiFactory.createShell().makePhoneShell();
        HWFactory hwFactory = new HWFactory();
        hwFactory.createPhone().makePhone();
        hwFactory.createShell().makePhoneShell();
    }

}

输出结果:

 

 抽象工厂模式相比工厂方法模式: 抽象工厂方法不再是单独的接口,而是生产一类产品的接口,可以生产多个相关联产品,接下来我们看下UML类图关系

 

  抽象工厂模式的使用场景:

    引用<<Java与模式>>的说法:

  1:一个系统不应当依赖于产品类实例如何创建,组合和表达的细节,这对于所有形态的工厂模式都是重要的

  2:这个系统的产品有多于一个的产品族,而系统只消费其中某一族的产品(上面这一条叫做抽象工厂的原始用意)

  3:同属于一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来

  4:系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现

为什么会有这样的说法,我想就应该深入到抽象工厂模式的起源的具体场景去讨论这个问题

posted @ 2020-04-21 15:21  蚂蚁style  阅读(236)  评论(0编辑  收藏  举报