工厂模式主要分为 3 类:
- 简单工厂模式
- 工厂方法模式
- 抽象工程模式>
在讲解这三种设计模式之前,问大家一个问题:我们平常写代码的时候,对象是怎么创建的呢?
大家都知道的,直接 new 一个对象呗,比如 Class a = new Class();
没错,在大多数情况下,直接使用 new 关键字来创建对象没有问题,但有没有想过,如果创建对象需要一系列复杂的初始化操作,别人需要关联其他成员对象、查配置文件或者数据库,这时候怎么办呢?
这个时候,我们可以增加一个特殊的类–工厂类,专门负责对象的创建工作
工厂模式的主要解决的问题是,将原来分布在各个地方的对象创建过程单独抽离出来,交给工厂类负责创建。其他地方想要使用对象直接找工厂(即调用工厂的方法)获取对象。
今天就来讲讲这三种模式来举例了解一下
简单工厂模式
假设我们已领养宠物狗(dog)为例,这个类实例需要在许多地方被创建和初始化,而初始化的代码也比较复杂。
public class KejiDog {
    //构造函数
    public KejiDog(){
        // .....
    }
}
针对这种情况,我们可以构建一个狗店(工厂)专门负责创建狗对象,把柯基的初始化代码迁移到工厂类的创建方法当中:
public class kejiDogFactory {
    public Mask createKejiDog() {
        KejiDog kejiDog = new KejiDog();
        // .....
        return kejiDog;
    }
}
那么,如果店(工厂)中不只存在柯基呢,如果也有巴哥呢,那么该如何来创建对象呢?这时候我们可以给店(工厂)添加一系列的判断。
假设狗的类只是一个抽象接口,有两个子类“柯基”和“巴哥”分别实现了以下接口:
public interface DogShop {
    void show();
}
public class Keji implements DogShop {
    @Override
    public void show() {
        System.out.println("我是柯基");
    }
}
public class Bage implements DogShop {
    @Override
    public void show(){
        System.out.println("我是巴哥");
    }
}
那么店(工厂)该如何创建这两种类型的宠物狗呢?
很简单,在创建方法中传入参数(这里的参数是type),根据参数来做条件判断,决定创建什么样的宠物狗:
public class DogShopFactory{
    public DogShop createDog(String type) {
        DogShop dogShop = null;
        if("柯基".equals(type)){
            dogShop = new Keji();
            // .....
            // HighEndMask的100行初始化代码
        }else if("巴哥".equals(type)){
            dogShop =  new Bage();
            // .....
            // LowEndMask的100行初始化代码
        }
        return dogShop;
    }
}
最后想要创建什么样狗的对象,只需传入对应的类型名称即可,如下:
public class Test {
    public static void main(String[] args) {
        DogShopFactory factory = new DogShopFactory();
        DogShop maskA = factory.createDog("柯基");
        DogShop maskB = factory.createDog("巴哥");
        maskA.show();
        maskB.show();
    }
}
通过工程类创建对象,并且传入参数决定具体类对象的做法,就是简单工厂模式
但是有一个问题不知道大家发现没有?
如果增加不同狗的类型,店(工厂)的创建方法中就要增加新的if-else判断,这种方式并不符合面向对象的开放/封闭原则吧
注:所谓面向对象的开放-封闭原则,就是在程序中对“扩展”开放,对“修改”封闭。如果每次业务改动都要增加新的if-else,就涉及对旧有代码的修改,不但容易出错,可读性也不好。
这里想要解决if-else的问题,可以为每一个狗类创建对应的工厂子类,这些工厂子类分别实现抽象的工厂接口,这样的话,只要我们实例化不同的工厂子类,调用创建方法,得到的就是对应狗的对象。
工厂方法模式
public interface DogShopFactory {
    IMask createMask();
}
public class KejiFactory implements DogShopFactory{
    @Override
    public DogShop createMask() {
        DogShop mask =  new Keji();
        // .....
        return mask;
    }
}
public class BageFactory implements DogShopFactory{
    @Override
    public DogShop createMask() {
        DogShop mask =  new Bage();
        // .....
        return mask;
    }
}
在代码中,工厂类变成了抽象的接口,柯基工厂和巴哥工厂这两个子类分别实现了该接口。
想要创建什么样的口罩对象,只需实例化不同的工厂子类,调用相同的创建方法,无需再传入参数。
public class Test {
    public static void main(String[] args) {
        KejiFactory factoryA = new KejiFactory();
        BageFactory factoryB = new BageFactory();
        DogShop maskA = factoryA.createMask();
        DogShop maskB = factoryB.createMask();
        maskA.show();
        maskB.show();
    }
}
到这里的话又有一个问题了:如果需要创建的子类越来越多,不只是有狗,也有猫的话,难道每个子类都要对应一个工厂类吗
在抽象工厂模式当中这个问题得到了很好的解决
抽象工厂模式

狗和猫是两个抽象接口,分别拥有贵和不贵两个实现类:
public interface Dog {
    void showMask();
}
public class NotExpensiveDog implements Dog {
    @Override
    public void showMask(){
        System.out.println("不贵的狗");
    }
}
public class ExpensiveDog implements IMask {
    @Override
    public void showMask() {
        System.out.println("贵的狗");
    }
}
public interface Cat {
    void showSuit();
}
public class NotExpensiveCat implements Cat {
    @Override
    public void showSuit() {
        System.out.println("不贵的猫");
    }
}
public class ExpensiveCat implements Cat {
    @Override
    public void showSuit() {
        System.out.println("贵的猫");
    }
}
接下来是工厂类,由于动物分成了贵和不贵两大组,工厂也相应分成了贵工厂和不贵工厂,各自负责自己的的创建:
public interface IFactory {
    IMask createMask();
    IProtectiveSuit createSuit();
}
public class NotExpensiveFactory implements IFactory {
    @Override
    public Dog createMask() {
        Dog dog =  new NotExpensiveDog();
        // .....
        return dog;
    }
    @Override
    public IProtectiveSuit createSuit() {
        Cat cat =  new NotExpensiveCat();
        // .....
        return cat;
    }
}
public class ExpensiveFactory implements IFactory {
    @Override
    public IMask createMask() {
        Dog dog =  new ExpensiveDog();
        // .....
        return dog;
    }
    @Override
    public IProtectiveSuit createSuit() {
        Cat cat =  new ExpensiveCat();
        // .....
        return cat;
    }
}
通过实例化不同的工厂子类,调用不同的创建方法,可以创建出不同的产品。
public class Test {
    public static void main(String[] args) {
        IFactory factoryA = new NotExpensiveFactory();
        IFactory factoryB = new ExpensiveFactory();
        //创建不贵的狗
        Dog maskA = factoryA.createMask();
        //创建贵的狗
        Dog maskB = factoryB.createMask();
        //创建不贵的猫
        Cat suitA = factoryA.createSuit();
        //创建贵的猫
        Cat suitB = factoryB.createSuit();
        maskA.showMask();
        maskB.showMask();
        suitA.showSuit();
        suitB.showSuit();
    }
}
最后
这里有个问题,到底什么时候该用工厂方法模式,而非简单工厂模式呢?
当对象的创建逻辑比较复杂,不只是简单的 new 一下就可以,而是要组合其他类对象,做各种初始化操作的时候,我们推荐使用工厂方法模式,将复杂的创建逻辑拆分到多个工厂类中,让每个工厂类都不至于过于复杂。
而使用简单工厂模式,将所有的创建逻辑都放到一个工厂类中,会导致这个工厂类变得很复杂
 
                   
                   
                   
                   
                             
                     
       
           
                 
                 
                 
                 
                 
                
               
                 
                 
                 
                 
                
               
                 
                 扫一扫
扫一扫
                     
              
             
                   2931
					2931
					
 被折叠的  条评论
		 为什么被折叠?
被折叠的  条评论
		 为什么被折叠?
		 
		  到【灌水乐园】发言
到【灌水乐园】发言                                
		 
		 
    
   
    
   
             
            


 
            