Java 工厂模式

简单工厂模式

简单的工厂模式,就是把实例的创建单独提取在一个类里去完成。

比如:有一个接口 Car,和三个具体品牌:BMW,BENZ,BYD。创建一个 CarFactory 工厂类来生产car,当我需要 Car 的实例时,通过工厂来创建。

//car接口
public interface Car {
    public void run();
}


//三个具体的实现类
public class BMW implements Car{
    @Override
    public void run() {
        System.out.println("一辆宝马车在跑");
    }
}

public class BENZ implements Car{
    @Override
    public void run() {
        System.out.println("一辆奔驰车在跑");
    }
}

public class BYD implements Car{
    @Override
    public void run() {
        System.out.println("一辆比亚迪在跑");
    }
}


//SimpleFactory工厂类,用来实例化 Car,生产车
public class SimpleFactory {
    public static Car getCar(String carName){
        if(carName.equals("BENZ")){
            return new BENZ();
        }else if(carName.equals("BMW")){
            return new BMW();
        }else if(carName.equals("BYD")){
            return new BYD();
        }else{
            return null;
        }
    }
}


//测试类
public class Test {
    public static void main(String[] args) {
        Car car1 = SimpleFactory.getCar("BMW");
        car1.run();
        
        Car car2 = SimpleFactory.getCar("BENZ");
        car2.run();
        
        Car car3 = SimpleFactory.getCar("BYD");
      car3.run();
    }
}

简单工厂还有两种写法:一种是利用了反射,一种是在工厂里写多个方法。
不同的写法各有利弊:

利用反射,好处是当增加产品的时候不用修改工厂类的代码,缺点就是写法复杂,不易用

public class StaticFactory {
    @SuppressWarnings("unchecked")
    public static <T extends Car> T newInstance(Class<T> claz){
        T result = null;
        try {
            result = (T) Class.forName(claz.getName()).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
}

多方法是在工厂类的写多个方法,当需要扩展的时候,只需要增加一个方法即可,不用修改原代码的逻辑;而只有一个方法的写法,要在方法内部用 if 或是 switch 进行判断,要扩展就要增加判断语句。

public class MultiFactory {
    
    public static Car getBenz(){
        return new BENZ();
    }
    public static Car getBmw(){
        return new BMW();
    }
    public static Car getByd(){
        return new BYD();
    }
}

工厂方法模式

工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化哪一个。
工厂方法模式等于把工厂也抽象了一层。
当需求变化,只需要增删相应的类,不需要修改已有的类。

//抽象的工厂类
public abstract class AbstractFactory {
   public abstract Car getCar();
}

//具体的工厂类
public class BenzFactory extends AbstractFactory{
    @Override
    public Car getCar() {
        return new BENZ();
    }
}

public class BmwFactory extends AbstractFactory{
    @Override
    public Car getCar() {
        return new BMW();
    }
}

//当需要增加 BYD 工厂时,直接增加一个实现类即可,不用再修改原来的工厂
public class BydFactory extends AbstractFactory{
    @Override
    public Car getCar() {
        return new BYD();
    }
}

//测试类
public class Test {
    public static void main(String[] args) {
        AbstractFactory factory = new BenzFactory();
        Car car = factory.getCar();
        car.run();
    }
}

抽象工厂模式

为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。
抽象工厂模式面对是产品族,就是可视为一组的多个产品,抽象工厂 模式能保证客户端始终只使用同一个产品族中的对象。比如:汽车和自行车是不同的产品,有一个抽象工厂生产汽车和自行车,BYD是一个具体的工厂,生产货车和产公路自行车;BMW也是一个具体的工厂,生产客车和山地自行车。

工厂方法模式面对的是单一产品,而抽象工厂模式面对的是产品族,这是二者最大的区别。

//产品接口和具体实现类
//汽车接口和实现类
public interface Car {
    public void run();
}
public class Bus implements Car{
    @Override
    public void run() {
        System.out.println("一辆公交车在跑");
    }
}
public class Truck implements Car{
    @Override
    public void run() {
        System.out.println("一辆货车在跑");
    }
}

//自行车接口和实现类
public interface Bike {
    public void run();
}
public class MountainBike implements Bike{
    @Override
    public void run() {
        System.out.println("一辆山地自行车在跑");
    }
}
public class RoadBike implements Bike{
    @Override
    public void run() {
        System.out.println("一辆公路自行车在跑");
    }
}


//抽象的工厂类
public abstract class AbstractFactory {
//生产抽象的产品
     public abstract Car getCar();
     public abstract Bike getBike();
}
//具体的工厂类
public class BmwFactory extends AbstractFactory{
    @Override  //Bmw工厂生产客车和山地自行车
    public Car getCar() {
        System.out.println("这是 BMW 工厂生产的客车 ");
        return new Bus();
    }
    @Override
    public Bike getBike() {
        System.out.println("这是 BMW 工厂生产的山地自行车 ");
        return new MountainBike();
    }
}

public class BydFactory extends AbstractFactory{
    @Override  //Byd工厂生产货车和公路自行车
    public Car getCar() {
        System.out.println("这是 BYD 工厂生产的货车 ");
        return new Truck();
    }
    @Override
    public Bike getBike() {
        System.out.println("这是 BYD 工厂生产的公路自行车 ");
        return new RoadBike();
    }
}



//测试类
public class Test {
    public static void main(String[] args) {
    
    AbstractFactory factoryByd = new BydFactory();
    factoryByd.getBike().run();
    factoryByd.getCar().run();
    
    AbstractFactory factoryBmw = new BmwFactory();
    factoryBmw.getBike().run();
    factoryBmw.getCar().run();
    }
}

工厂模式就是把实例对象的产生封装起来,只要知道工厂类,就能创建出实例来,而不用关心实例是如何创建出来的,使创建和使用分离,达到解耦的目的。

工厂模式适用于构建同产品类型(同一个接口或基类)的不同对象时,尤其是当创建实例的条件比较复杂时,或是创建对象需要很多参数而这些参数中大部分又是固定的时候,工厂模式的优点就很明显了。当然,缺点也很明显,不容易扩展,要增加一个产品就要修改多处代码。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容

  • 目录1.概念2.角色3.工厂执行的具体流程简单工厂模式(静态工厂方法)工厂模式抽象工厂模式4.分类5.总结6.学习...
    在挖坑的猿阅读 738评论 0 4
  • 文章部分内容转载自:http://blog.csdn.net/zhangerqing 一、设计模式的分类 总体来说...
    j_cong阅读 2,055评论 0 20
  • 设计模式汇总 一、基础知识 1. 设计模式概述 定义:设计模式(Design Pattern)是一套被反复使用、多...
    MinoyJet阅读 3,897评论 1 15
  • 一、工厂模式介绍 工厂模式专门负责将大量有共同接口的类实例化。工厂模式可以动态决定将哪一个类实例化,不必事先知道每...
    端木轩阅读 12,688评论 1 20
  • 2016-07-12 华杉 用之则行,舍之则藏。不在其位,不谋其政。用之则行,但并不是非用不可。舍之则藏,也不是故...
    郁萍阅读 148评论 0 0