工厂方法模式和抽象工厂模式

1.为什么需要使用工厂模式

工厂模式是使用工厂方法创建对象代替new的方式创建对象,那为什么不直接使用new呢?一般的对象都是直接使用new 类名()创建,最多增加简单的参数。但是有些对象是比较特殊的它需要执行一些复杂的操作才能创建一个完整的对象,比如加载配置文件,参数校验等。每次得到这个对象需要写一大段的代码,不便于代码维护。而且如果有一天需要修改创建该对象的部分逻辑,需要同时在多个地方修改,增加了出错的可能性。

2.场景

有一个电器工厂,根据不同的电器保养方式不一样,在重构前结构可能是下面的:

public class ApplianceManager {
    public void store() {
        // ...........
        System.out.println("对象创建前操作,省略");
        // 电器
        Appliance appliance = null;
        String type = "tv";
        if (type.equals("tv")) {
            TV tv= new TV();
            // tv保养
        } else if (type.equals("Refrigerator")) {
            Refrigerator refrigerator= new Refrigerator();
            // refrigerator保养
        } else if (type.equals("Washer")) {
            Washer washer= new Washer();
            // washer保养
        } else {
            throw new RuntimeException("不支持类型");
        }
        // ...........
        System.out.println("对象创建后操作,省略");
    }
}

缺点:每次需要修改电器子类,都需要修改这部分代码,难以维护。

2.1 简单工厂

2.1.1 定义几种电器

public interface Appliance {
    /**
     * 保养
     */
   void maintain();
}
public class Refrigerator implements Appliance {
    @Override
    public void maintain() {
        System.out.println("冰箱保养");
    }
}
public class TV implements Appliance {
    @Override
    public void maintain() {
        System.out.println("电视保养");
    }
}
public class Washer implements   Appliance {
    @Override
    public void maintain() {
        System.out.println("洗衣机保养");
    }
}


2.1.2 电器工厂(核心)

public class ApplianceFactory {

    public static Appliance getAppliance(String type){
        Appliance appliance = null;
        if (type.equals("tv")) {
            appliance = new TV();
        } else if (type.equals("Refrigerator")) {
            appliance = new Refrigerator();
        } else if (type.equals("Washer")) {
            appliance = new Washer();
        } else {
            throw new RuntimeException("不支持类型");
        }
        return appliance;
    }
}

2.1.3 管理电器的存储

public class ApplianceManager {

    public void maintain() {
        // ...........
        System.out.println("对象创建前操作,省略");
        // 电器
        Appliance appliance = ApplianceFactory.getAppliance("tv");
        appliance.maintain();
        // ...........
        System.out.println("对象创建后操作,省略");
    }
}

缺点:每当增加一个新的电器之后,就要修改ApplianceFactory类,并且该类会越来越重。所以需要使用接下来要介绍的工厂方法模式拆解这个类。

2.2 工厂方式模式

2.2.1 工厂接口

public interface ApplianceFactory {

    Appliance getAppliance();

}

2.2.2 实现各自的工厂类

public class RefrigeratorFactory implements ApplianceFactory {
    @Override
    public Appliance getAppliance() {
        return new Refrigerator();
    }
}
public class WasherFactory implements ApplianceFactory {
    @Override
    public Appliance getAppliance() {
        return new Washer();
    }
}
public class TVFactory implements  ApplianceFactory {
    @Override
    public Appliance getAppliance() {
        return new TV();
    }
}

2.2.2 电器管理

public class ApplianceManager {

    public void maintain() {
        // ...........
        System.out.println("对象创建前操作,省略"); 
        
        // 为了方便扩展可以使用配置获取
        TVFactory tvFactory = new TVFactory();
        Appliance appliance = tvFactory.getAppliance();
        appliance.maintain();

        // ...........
        System.out.println("对象创建后操作,省略");
    }
}

缺点:存在大量的产品就会产生大量的类,如果能将某一几个产品绑定在一起,就可以成倍地减少类的数量,这就是抽象工厂的设计思路。它有一个产品族的概念,将多个产品让一个工厂生产。比如:格力可以生产电视,冰箱和洗衣机,美的也能生产这些产品,所以只要两个工厂类:格力工厂类和美的工厂类就可以完成工厂方法中原本需要六个类实现的功能。

2.3 抽象工厂

2.3.1 定义一个产品族工厂

public interface ApplianceFactory {

    Appliance getTV();

    Appliance getRefrigerator();

    Appliance getWasher();

}

2.3.2 定义各种具体的产品

public class GreeRefrigerator extends Refrigerator{
    @Override
    public void maintain() {
        System.out.println("格力冰箱保养");
    }
}
public class GreeTV extends TV {
    @Override
    public void maintain() {
        System.out.println("格力电视保养");
    }
}
public class GreeWasher extends Washer {
    @Override
    public void maintain() {
        System.out.println("格力洗衣机保养");
    }
}
public class MideaTV extends TV {
    @Override
    public void maintain() {
        System.out.println("美的电视保养");
    }
}
public class MideaWasher extends Washer {
    @Override
    public void maintain() {
        System.out.println("美的洗衣机保养");
    }
}
public class MideaRefrigerator extends Refrigerator{
    @Override
    public void maintain() {
        System.out.println("美的冰箱保养");
    }
}

2.3.3 具体产品族工厂

// 格力
public class GreeApplianceFactory implements ApplianceFactory {
    @Override
    public Appliance getTV() {
        return new GreeTV();
    }

    @Override
    public Appliance getRefrigerator() {
        return new GreeRefrigerator();
    }

    @Override
    public Appliance getWasher() {
        return new GreeWasher();
    }
}

// 美的
public class MideaApplianceFactory implements ApplianceFactory {
    @Override
    public Appliance getTV() {
        return new MideaTV();
    }

    @Override
    public Appliance getRefrigerator() {
        return new MideaRefrigerator();
    }

    @Override
    public Appliance getWasher() {
        return new MideaWasher();
    }
}

2.3.4 电器管理

public class ApplianceManager {

    public void maintain() {
        // ...........
        System.out.println("对象创建前操作,省略");
        
        
        GreeApplianceFactory greeApplianceFactory = new GreeApplianceFactory();
        Appliance tv = greeApplianceFactory.getTV();
        tv.maintain();
        
        
        // ...........
        System.out.println("对象创建后操作,省略");
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值