欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java设计模式2-工厂模式

程序员文章站 2024-01-21 15:02:52
...

1、为什么要使用工厂模式?

在面向对象编程中, 最通常的方法是一个new操作符产生一个对象实例,new操作符就是用来构造对象实例的。
但是在一些情况下, new操作符直接生成对象会带来一些问题。
许多类型对象的创造需要一系列的步骤: 
    你可能需要计算或取得对象的初始设置; 
    选择生成哪个子对象实例; 
    或在生成你需要的对象之前必须先生成一些辅助功能的对象。 
在这些情况,新对象的建立就是一个 “过程”。

解决方案:建立一个工厂来创建对象

2、工厂模式分类(3类):

a.简单工厂模式(Simple Factory) 
b.工厂方法模式(Factory Method) 
c.抽象工厂模式(Abstract Factory) 

这三种模式从上到下逐步抽象,并且更具一般性。 
    有的将工厂模式分为两类:工厂方法模式(Factory Method)与抽象工厂模式(Abstract Factory)。
    将简单工厂模式(Simple Factory)看为工厂方法模式的一种特例,两者归为一类。

3、简单工厂模式:

又叫静态工厂,是工厂模式三中状态中结构最为简单的。主要有一个静态方法,用来接受参数,并根据参数来决定返回实现同一接口的不同类的实例。
这个模式本身很简单而且使用在业务较简单的情况下。一般用于小项目或者具体产品很少扩展的情况(这样工厂类才不用经常更改)。

a.我们先为所有产品定义一个共同的产品接口.
    public interface Product{} 

b.让这个工厂的所有产品都必须实现此接口
        public class Washer implements Product{ 
           public Washer(){ 
               System.out.println("制造洗衣机"); 
           } 
        } 

        public class Icebox implements Product{ 
           public Icebox(){ 
               System.out.println("制造冰箱"); 
           } 
        } 
c.写一个工厂类,有它来负责生产以上的产品
        public class SimpleFactory { 
            public static Product factory(String productName) throws Exception{ 
                if(productName.equals("Washer")){ 
                    return new Washer(); 
                }else if(productName.equals("Icebox")){ 
                    return new Icebox(); 
                }else{ 
                    throw new Exception("没有该产品"); 
                } 
            } 
        } 
d.使用
        public static void main(String[] args) { 
            try { 
                SimpleFactory.factory("Washer"); 
                SimpleFactory.factory("Icebox"); 
            } catch (Exception e) { 
                e.printStackTrace(); 
            } 
        }
总结:
    简单工厂的核心就是一个SimpleFactory类, 看起来使用很方便。
    缺点:
        1.我们传递文本参数的时候很可能书写错误。
        2.我们每次想要增加一种新产品的时候,都必须修改SimpleFactory的原代码。
        3.当我们拥有很多很多产品的时候,而且产品之间又存在复杂的层次关系的时候,这个类必须拥有复杂的逻辑判断能力,其代码量也将不断地激增。
        4.整个系统都严重依赖SimpleFactory类,只要SimpleFactory类一出问题,系统就进入不能工作的状态。(最致命)
以上的不足将在工厂模式的另外两种状态中得到解决。

4、工厂方法模式:

为了降低风险和为日后的维护、扩展做准备,我们需要对它进行重构,引入工厂方法。
工厂方法为工厂类定义了接口,用多态来削弱了工厂类的职能。

a.我们先给工厂定义一个接口
public interface Factory{ 
    public Product create(); 
} 
b.再为所有产品定义一个共同的产品接口.
public interface Product{} 
c.让这个工厂的所有产品都必须实现此产品接口
public class Washer implements Product{ 
   public Washer(){ 
       System.out.println("制造洗衣机"); 
   } 
} 

public class Icebox implements Product{ 
   public Icebox(){ 
       System.out.println("制造冰箱"); 
   } 
} 
d.接下来,就是工厂方法的核心部分,也就是具体创建产品对象的具体工厂类 
//创建洗衣机的工厂 
public class CreateWasher implements Factory{ 
    @Override
    public Product create(){ 
        return new Washer(); 
    } 
} 

//创建冰箱的工厂 
public class CreateIcebox implements Factory{ 
    @Override
    public Product create(){ 
        return new Icebox(); 
    } 
} 
e.使用
public static void main(String[] args) { 
    try { 
        Factory factory = new CreateWasher();
        Product product = factory.create();
    } catch (Exception e) { 
        e.printStackTrace(); 
    } 
}
注意:
工厂方法和简单工厂的主要区别是,简单工厂是把创建产品的职能都放在一个类里面,而工厂方法则把不同的产品放在实现了工厂接口的不同工厂类里面。
    相比简单工厂模式优点:
        1.这样就算其中一个工厂类出了问题,其他工厂类也能正常工作,互相不受影响。   
        2.以后增加新产品,也只需要新增一个实现工厂接口工厂类,就能达到,不用修改已有的代码。
    缺点:
        工厂方法也有他局限的地方,那就是当面对的产品有复杂的等级结构的时候,
        例如,工厂除了生产家电外产品,还生产手机产品,这样一来家电是手机就是两大产品家族了,这两大家族下面包含了数量众多的产品,每个产品又有多个型号,这样就形成了一个复杂的产品树了。
        如果用工厂方法来设计这个产品家族系统,就必须为每个型号的产品创建一个对应的工厂类,
        当有数百种甚至上千种产品的时候,也必须要有对应的上百成千个工厂类,这就出现了传说的类爆炸,对于以后的维护来说,简直就是一场灾难。

5、抽象工厂模式:

抽象工厂是在工厂方法的基础上引进了分类管理的概念
工厂方法用来创建一个产品,它没有分类的概念,而抽象工厂则用于创建一系列产品,所以产品分类成了抽象工厂的重点,

例如:
工厂生产的所有产品都用都用大写字母来标明它们的型号,比如冰箱,就有“冰箱-A",“冰箱-B"。

a.我们为冰箱和洗衣机分别定义两个产品接口,以对他们进行分类。
//洗衣机接口 
public interface Washer{ 
} 

//冰箱接口 
public interface Icebox{ 
} 
b.接着,我们分别创建这两个接口的具体产品(注意,我们需要产品进行分类,就不需要Product接口了)
//洗衣机-A 
public class WasherA implements Washer{ 
   public WasherA(){ 
       System.out.println("洗衣机-A被制造了"); 
   } 
} 

//洗衣机-B 
public class WasherB implements Washer{ 
   public WasherB(){ 
       System.out.println("洗衣机-B被制造了"); 
   } 
} 

//冰箱-A 
public class IceboxA implements Icebox{ 
   public IceboxA(){ 
       System.out.println("冰箱-A被制造了"); 
   } 
} 

//冰箱-B 
public class IceboxB implements Icebox{ 
   public IceboxB(){ 
       System.out.println("冰箱-B被制造了"); 
   } 
} 
c.产品部分我们准备好了,接下来我们来处理工厂部分,我们先来定义工厂行为接口.
public interface Factory{ //注意我们Factory接口里面不再只有create()了,我们create具体的产品
    public Washer createWasher(); 
    public Icebox createIcebox(); 
}
d.接下来我创造具体的工厂类
    我们根据上面产品的接口,把型号A的产品分为一类,由一个工厂来管理,把型号为B的产品有另一个工厂管理,根据这个分类,我们可以实现如下的两个具体工厂类
//创建型号为A的产品工厂 
public class FactoryA implements Factory{ 
    //创建洗衣机-A 
    @Override
    public Washer createWasher(){ 
        return new WasherA(); 
    } 

    //创建冰箱-A 
    @Override
    public Icebox createIcebox(){ 
        return new IceboxA(); 
    } 
} 

//创建型号为B的产品工厂 
public class FactoryB implements Factory{ 
    //创建洗衣机-B
    @Override
    public Washer createWasher(){ 
        return new WasherB(); 
    } 

    //创建冰箱-B 
    @Override
    public Icebox createIcebox(){ 
        return new IceboxB(); 
    } 
}
e.使用
public static void main(String[] args) { 
    try { 
        Factory factory = new FactoryA();
        Washer washer = factory.createWasher();
    } catch (Exception e) { 
        e.printStackTrace(); 
    } 
}
以后要是要生产一种c类产品,只要实现一个FactoryC工厂,在工厂里面创造C类的产品
总结:
    工厂方法和抽象工厂,都有自己的应用场景,并没有什么优劣之分,但在应用抽象工厂之前,要先对创建的对象进行系统的分类,这点很重要。
    好的产品分类规则能为具体工厂类的选择调用和以后的扩展提供清晰的思路.