Java-工厂模式

工厂模式:主要用来实例化有共同接口的类,工厂模式可以动态决定应该实例化那一个类。

目录

一、工厂模式的形态

二、简单工厂(Simple Factory)

三、工厂方法(Factory Method)(优点在于横向扩展)

四、抽象工厂(Factory Method)

五、适用场景:


一、工厂模式的形态

工厂模式主要有以下几种形态:

  1. 简单工厂(Simple Factory)
  2. 工厂方法(Factory Method)
  3. 抽象工厂(Abstract Factory)


二、简单工厂(Simple Factory)

定义:专门定义一个类(第三方)来创建其他类实例(解耦,将客户端创建对象的操作解耦到外部第三方类),被创建的实例通常都具有共同的父类。  --用于没有产品族并且产品个数较少

eg:

首先定义一个抽象类:机器,可以用来生产电脑

然后定义多个具体产品类:产品流水线,每个流水线负责生产该品牌产品

最后定义一个工厂类:工厂类中有许多不同流水线,其中可以生产多品牌电脑

用户想要的时候,只用在客户端输入想要的产品,与此对应的产品就会从工厂中生产,用户不必知道是如何生产的

Java-工厂模式_第1张图片

组成:   a.一个抽象类           interface factory

             b.N个具体产品类     class MacBook implements factory{}     class Aline implements factory{}   ......

             c.一个工厂类           class RealFactory{ public static factory produce(String pro){...} }

//简单工厂模式

//定义一个抽象类,假设这是一个生产电脑的机器
interface factory{
    void create();
}


//----------------------   多个具体产品类  -------------------------------------
//定义一个产品类,使用此机器生产品牌电脑
class MacBook implements factory{
    @Override
    public void create() {
        System.out.println("生产一个MacBook电脑");
    }
}
class Acer implements factory{
    @Override
    public void create() {
        System.out.println("生产一个Acer电脑");
    }
}
class Aline implements factory{
    @Override
    public void create() {
        System.out.println("生产一个Aline电脑");
    }
}
//---------------------------------------------------------------


//定义一个工厂类,拥有几条流水线工程来生产不同品牌的电脑
class RealFactory{
    public static factory produce(String name) {
        if (name.equals("MacBook")) {
            return new MacBook();
        } else if (name.equals("Acer")) {
            return new Acer();
        } else if (name.equals("Aline")) {
            return new Aline();
        }
        System.out.println("此工厂不生产"+name);
        return null;
    }
}

public class SimpleFactory {
    public static void main(String[] args) {
        RealFactory fac = new RealFactory();
        System.out.println("请输入你想要的电脑:");
        Scanner in = new Scanner(System.in);
        String name = in.next();
        fac.produce(name).create();
    }

}

结果:

正确输入:     

错误输入:Java-工厂模式_第2张图片

 

       由上面的代码可以看出,简单工厂的核心就是一个RealFactory类,他拥有必要的逻辑判断能力和所有产品的创建权利,我们只需要向把定单给他,就能得到我们想要的产品。这使用起来似乎非常方便。

       但是,实际上,这个RealFactory有很多的局限。首先,我们每次想要增加一种新产品的时候,都必须修改RealFactory的原代码,这显然违反了开闭原则。其次,当我们拥有很多很多产品的时候,而且产品之间又存在复杂的层次关系的时候,这个类必须拥有复杂的逻辑判断能力,其代码量也将不断地激增,这非常不符合我们的编码原则。还有就是,整个系统都严重依赖RealFactory类,如果RealFactory类出问题,系统就进入不能工作的状态,这也是最为致命的一点....

所以简单工厂只适合于产品对象较少,且产品固定的需求,对于产品变化无常的需求来说显然不合适

以上的不足将在工厂模式的另外两种状态中得到解决。

 



 

三、工厂方法(Factory Method)(优点在于横向扩展

上面的代码告诉我们,简单工厂是整个模式的核心,一旦他出了问题,整个模式都将受影响而不能工作,为了降低风险和为日后的维护、扩展做准备,我们需要对它进行重构,引入工厂方法。

定义:工厂方法定义一个用来创建对象的接口,用多态来削弱了工厂类的职能,让子类决定实例化哪一个工厂。

eg:

          首先定义一个抽象类:机器,可以用来生产电脑

          然后定义多个具体产品类:产品流水线,每个流水线负责生产该品牌产品

          然后定义一个抽象工厂,工厂可以流水线生产电脑

          最后定义多个工厂类:每个工厂可以生产自己品牌的电脑

          用户想要的时候,只用找到对应品牌的工厂发送请求,与此对应的产品就会从工厂中生产,每个品牌工厂自己管理自己流水线电脑,其他的工厂产品出问题或者倒闭了都和自家的没关系:)

Java-工厂模式_第3张图片

组成:  a. 一个抽象产品类    interface Computre

            b.多个具体产品类   class MacBook implements Computre   。。。

            c.一个抽象工厂       interface ComputerFactory

            d.多个具体工厂(每个产品族对应一个具体工厂)   class msFactory implements ComputerFactory

interface Computre{
    void create();
}
//----------------------   多个具体产品类  -------------------------------------
class MacBook implements Computre{
    @Override
    public void create() { System.out.println("生产一个MacBook电脑"); }
}
class Aline implements Computre{
    @Override
    public void create() {System.out.println("生产一个外星人电脑");}
}
class Acer implements Computre{
    @Override
    public void create() {System.out.println("生产一个Acer电脑"); }
}
//------------------------------------------------------------------------------

interface ComputerFactory{
    Computre createComputer();
}

//----------------------   多个具体工厂   -------------------------------------
//弘基电脑工厂
class msFactory implements ComputerFactory{
    @Override
    public Computre createComputer() {
        return new Acer();
    }
}
//苹果产品工厂
class AppleFactory implements ComputerFactory{
    @Override
    public Computre createComputer() {
        return new MacBook();
    }
}
//微软产品工厂
class AcerFactory implements ComputerFactory{
    @Override
    public Computre createComputer() {
        return new Aline();
    }
}
//------------------------------------------------------------------------------

public class FactoryMethod{
    public static void main(String[] args) throws InterruptedException {
        ComputerFactory computerFactory = new AppleFactory();
        Computre computre = computerFactory.createComputer();
        computre.create();
    }
}

结果:

 

        从上面创建产品的栗子可以看出,工厂方法和简单工厂的主要区别是,简单工厂是把创建产品的职能都放在一个类里面,而工厂方法则把不同的产品放在实现了工厂接口的不同工厂类里面,这样就算其中一个工厂类出了问题,其他工厂类也能正常工作,互相不受影响,以后增加新产品,也只需要新增一个实现工厂接口工厂类,就能达到,不用修改已有的代码。

       但是工厂方法也有他局限的地方,那就是当面对的产品有复杂的等级结构的时候,例如,苹果工厂除了生产电脑,还生产手机产品,这样一来电脑和手机就是两大产品家族了,这两大家族下面包含了数量众多的产品,每个产品又会有多个型号,这样就形成了一个复杂的产品树了。如果用工厂方法来设计这个产品家族系统,就必须为每个型号的产品创建一个对应的工厂类,当有数百种甚至上千种产品的时候,也必须要有对应的上百成千个工厂类,这在现实中显然是不可能发生的。

 

四、抽象工厂(Factory Method)

抽象工厂:意的意图在于创建一系列互相关联或互相依赖的对象。

特点:提供一个创建一系列相关或相互依赖对象的接口(抽象工厂、多条产品线),而无需指定他们具体的类。

       抽象工厂和工厂方法的模式基本一样,区别在于,工厂方法是生产一个具体的产品,而抽象工厂可以用来生产一组相同,有相对关系的产品;重点在于一组,一批,一系列。

举个例子,假如生产华为手机,小米手机有很多系列,华为荣耀系列、华为P系列、华为Nova系列等;假如Nova3生产需要的配件有麒麟970的处理器,6.3英寸屏幕,而荣耀10只需要麒麟940的处理器和5.84寸的屏幕就可以了;用抽象工厂来实现:

//抽象工厂
//CPU接口
interface Cpu {
    void run();

    class Cpu940 implements Cpu {
        @Override
        public void run() { System.out.println("我的CPU是麒麟940呦"); }
    }

    class Cpu970 implements Cpu {
        @Override
        public void run() { System.out.println("我的CPU是麒麟970"); }
    }
}
//屏幕接口
interface Screen {
    void size();

    class Screen5 implements Screen {
        @Override
        public void size() { System.out.println("我的屏幕是5寸"); }
    }

    class Screen6 implements Screen {
        @Override
        public void size() { System.out.println("我的屏幕是6寸"); }
    }
}

//工厂接口
interface PhoneFactory {
    Cpu getCpu();//使用的cpu
    Screen getScreen();//使用的屏幕
}

//--------------------------------具体实现类---------------------------
//Nova3
class Nova3Factory implements PhoneFactory {
    @Override
    public Cpu getCpu() { return new Cpu.Cpu970(); }

    @Override
    public Screen getScreen() { return new Screen.Screen6(); }
}
//荣耀10
class HonorFactory implements PhoneFactory {
    @Override
    public Cpu getCpu() { return new Cpu.Cpu940(); }
    
    @Override
    public Screen getScreen() { return new Screen.Screen5(); }
}
//-------------------------------------------------------------------

public class AbstFactory {
    public static void main(String[] args) {
        PhoneFactory phone = new Nova3Factory();
        phone.getCpu().run();
        phone.getScreen().size();

    }
}

从以上的例子可以看出,抽象工厂可以解决一系列的产品生产的需求,对于大批量,多系列的产品,用抽象工厂可以更好的管理和扩展;

 

五、适用场景:

无论是简单工厂模式,工厂方法模式还是抽象工厂模式,它们都具有类似的特性,适用场景也十分类似。

        无论是简单工厂模式,工厂方法模式,还是抽象工厂模式,他们都属于工厂模式,在形式和特点上也是极为相似的,他们的最终目的都是为了解耦。在使用时,我们不必去在意这个模式到底工厂方法模式还是抽象工厂模式,因为他们之间的演变常常是令人琢磨不透的。经常你会发现,明明使用的工厂方法模式,当新需求来临,稍加修改,加入了一个新方法后,由于类中的产品构成了不同等级结构中的产品族,它就变成抽象工厂模式了;而对于抽象工厂模式,当减少一个方法使的提供的产品不再构成产品族之后,它就演变成了工厂方法模式。

        所以,在使用工厂模式时,只需要关心降低耦合度的目的是否达到了。使用工厂方法后,调用端的耦合度大大降低了。并且对于工厂来说,是可以扩展的,以后如果想组装其他的产品,只需要再增加一个工厂类的实现就可以。无论是灵活性还是稳定性都得到了极大的提高。

 


 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(JavaSE)