HeadFirst设计模式-工厂模式(基于汽车工厂和手机工厂)

工厂模式

本次主要讲述三个内容:

  • 简单工厂模式
  • 工厂方法模式
  • 抽象工厂模式

依赖倒置原则

设计原则:要依赖抽象,不要依赖具体类。

不能让高层组件依赖底层组件,而且,不管高层或底层组件,“两者”都应该依赖于抽象。
这个原则告诉我们,应该重写代码以便于我们依赖抽象类,而不依赖具体类。

指导方针:

  • 变量不可以持有具体类的引用。(如果使用new,就会持有具体类的引用。你可以改用工厂类避开这样的做法。)
  • 不要让类派生自具体类。(如果派生自具体类,你就会依赖具体类。请派生自一个抽象(接口或抽象类))
  • 不要覆盖基类中已实现的方法。(如果覆盖基类已经实现的方法,那么你的基类将就不是一个真正适合被继承的抽象。基类中已实现的方法,应该由所有的子类共享)

简单工厂模式

简单工厂模式不是一个“真正的”设计模式,只能说是一种编程习惯。
比如建立一个抽象类Car,然后用子类来继承。用SimpleCarFactory来生成对象(里面包含选择相应对象的逻辑处理),CarStrore直接调用SimpleCarFactory即可。

如上图所示。
代码实现如下:
Car :

package com.bestqiang.easyfactory;

/** * @author BestQiang */
public abstract class Car {
    private String color;
    private String price;
    private String speed;

    public abstract void go();
    public abstract void clear();

    @Override
    public String toString() {
        return "Car{" +
                "color='" + color + '\'' +
                ", price='" + price + '\'' +
                ", speed='" + speed + '\'' +
                '}';
    }

    public void sayHello() {
        System.out.println("我是" + color + "汽车," + " 我的价格是: " + price + "," + "速度是:"
                + speed);
    }

    public String getSpeed() {
        return speed;
    }

    public void setSpeed(String speed) {
        this.speed = speed;
    }

    public String getColor() {
        return color;
    }

    public String getPrice() {
        return price;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public void setPrice(String price) {
        this.price = price;
    }
}

BlueCar:

package com.bestqiang.easyfactory;

/** * @author BestQiang */
public class BlueCar extends Car {

    public BlueCar() {
        super("blue","2000$", "888km/s");
    }

    @Override
    public void go() {
        System.out.println("蓝汽车清洗完成了!");
    }

    @Override
    public void clear() {
        System.out.println("蓝汽车可以开走了!");
    }
}

RedCar:

package com.bestqiang.easyfactory;

/** * @author BestQiang */
public class RedCar extends Car {

    public RedCar() {
        super("red","1000$", "999km/s");
    }

    @Override
    public void go() {
        System.out.println("红汽车可以开走了!");
    }

    @Override
    public void clear() {
        System.out.println("红汽车清洗完成了!");
    }
}


SimpleFactory:

package com.bestqiang.easyfactory;

/** * @author BestQiang */
public class SimpleCarFactory {
    public Car createCar(String type) {
        Car car = null;
        if(type.equals("red")) {
            return new RedCar();
        } else if (type.equals("blue")) {
            return new BlueCar();
        }
        return car;
    }
}

CarStore:

package com.bestqiang.easyfactory;

/** * @author BestQiang */
public class CarStore {
    SimpleCarFactory simpleCarFactory = new SimpleCarFactory();

    public Car orderCar(String type) {
        Car car = simpleCarFactory.createCar(type);
        car.sayHello();
        car.clear();
        car.go();
        return car;
    }
}

Main:

package com.bestqiang.easyfactory;

/** * @author BestQiang */
public class Main {
    public static void main(String[] args) {
    	// 没有依赖抽象类,下面的工厂模式会对其改进
        CarStore carStore = new CarStore();
        Car blue = carStore.orderCar("blue");
        Car red = carStore.orderCar("red");
        System.out.println(blue);
        System.out.println(red);
    }
}

运行结果:

我是blue汽车, 我的价格是: 2000$,速度是:888km/s
蓝汽车可以开走了!
蓝汽车清洗完成了!
我是red汽车, 我的价格是: 1000$,速度是:999km/s
红汽车清洗完成了!
红汽车可以开走了!
Car{color='blue', price='2000$', speed='888km/s'}
Car{color='red', price='1000$', speed='999km/s'}

Process finished with exit code 0

工厂方法模式

刚才的简单工厂模式,只有一个工厂,不能动态的切换工厂。
所有的工厂模式都用来封装对象的创建。工厂方法模式(Factory Method Pattern)通过让子类决定该创建的对象是什么,来达到将对象创建的过程封装的目的。

简单工厂把全部的事情,在一个地方都处理完了,然而工厂方法却是创建一个框架,让子类决定要如何实现。等于说是
如下图所示:

简单工厂的做法,可以将对象的创建封装起来,但是简单工程不具备工厂方法的弹性,因为简单工厂不能变更正在创建的产品。Main新建工厂的时候直接new抽象类就ok了。

工厂类的实现代码:
CarStoreF:

package com.bestqiang.factory;

import com.bestqiang.easyfactory.Car;
import com.bestqiang.easyfactory.SimpleCarFactory;

/** * @author BestQiang */
public abstract class CarStoreF {

    public Car orderCar(String type) {
        Car car = createCar(type);
        car.sayHello();
        car.clear();
        car.go();
        return car;
    }

    protected abstract Car createCar(String type);

}

HuaweiCarStore:

package com.bestqiang.factory;

import com.bestqiang.easyfactory.BlueCar;
import com.bestqiang.easyfactory.Car;
import com.bestqiang.easyfactory.RedCar;

/** * @author BestQiang */
public class HuaweiCarStore extends CarStoreF {
    @Override
    protected Car createCar(String type) {
        Car car = null;
        if(type.equals("red")) {
            System.out.println("Huawei出品");
            return new RedCar();
        } else if (type.equals("blue")) {
            System.out.println("Huawei出品");
            return new BlueCar();
        }
        return car;
    }
}


XiaomiCarStore:

package com.bestqiang.factory;

import com.bestqiang.easyfactory.BlueCar;
import com.bestqiang.easyfactory.Car;
import com.bestqiang.easyfactory.RedCar;

/** * @author BestQiang */
public class XiaomiCarStore extends CarStoreF {
    @Override
    protected Car createCar(String type) {
        Car car = null;
        if(type.equals("red")) {
            System.out.println("小米出品");
            return new RedCar();
        } else if (type.equals("blue")) {
            System.out.println("小米出品");
            return new BlueCar();
        }
        return car;
    }
}


Main:

package com.bestqiang.factory;

import com.bestqiang.easyfactory.Car;
import com.bestqiang.easyfactory.CarStore;

/** * @author BestQiang */
public class Main {
    public static void main(String[] args) {
    	// 依赖于抽象类
        CarStoreF carStore = new HuaweiCarStore();
        Car blue = carStore.orderCar("blue");
        Car red = carStore.orderCar("red");
        System.out.println(blue);
        System.out.println(red);
    }
}

运行结果:

我是blue汽车, 我的价格是: 2000$,速度是:888km/s
蓝汽车可以开走了!
蓝汽车清洗完成了!
我是red汽车, 我的价格是: 1000$,速度是:999km/s
红汽车清洗完成了!
红汽车可以开走了!
Car{color='blue', price='2000$', speed='888km/s'}
Car{color='red', price='1000$', speed='999km/s'}

Process finished with exit code 0

抽象工厂模式

抽象工程模式: 提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。

抽象工厂允许客户使用抽象的接口来创建一组相关的产品,而不需要知道(或关心)实际产出的具体产品是什么。这样一来,客户就从具体的产品中被解耦。

抽象工厂定义了一个接口,所有的具体工程都必须实现此接口,这个接口包含一组方法用来生产产品。
当要创建产品家族和想让制造的相关产品集合起来时,可以使用抽象工厂。

可以这样理解,现在汽车工厂只生产汽车,现在如果还想生产手机,再继承原来汽车的抽象类,复用抽象类的已有的方法,实现抽象方法,就不合适了。那就建立一个抽象工厂,而且把抽象工厂设置为接口,把所有涉及的产品都写进去,然后后面再实现这个接口。
又可以这样理解,抽象工厂比工厂模式高一个级别,抽象工厂在乎的是生产的汽车还是手机,而工厂模式在乎的是生产的手机是什么样子的。在确定生产什么以后,工厂模式往往隐含在抽象工厂中。

下图中新增一个手机类,然后使用抽象工厂进行创建。

实现代码如下:
Phone:

package com.bestqiang.AFactory;

/** * @author BestQiang */
public abstract class Phone {
    private int color;
    private int price;

    @Override
    public String toString() {
        return "Phone{" +
                "color=" + color +
                ", price=" + price +
                '}';
    }

    public int getColor() {
        return color;
    }

    public void setColor(int color) {
        this.color = color;
    }

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    protected abstract void call();
}

HuaweiPhone:

package com.bestqiang.AFactory;

/** * @author BestQiang */
public class HuaweiPhone extends Phone {
    @Override
    protected void call() {
        System.out.println("华为,非一般的感觉!");
    }
}

XiaomiPhone:

package com.bestqiang.AFactory;

/** * @author BestQiang */
public class XiaomiPhone extends Phone {
    @Override
    protected void call() {
        System.out.println("小米,永不止步!");
    }
}

Factory:

package com.bestqiang.AFactory;

import com.bestqiang.easyfactory.Car;

/** * @author BestQiang */
public abstract class Factory {
    public abstract Phone phoneFactory(String type);
    public abstract Car carFactory(String type);
}

FactoryA:

package com.bestqiang.AFactory;

import com.bestqiang.easyfactory.BlueCar;
import com.bestqiang.easyfactory.Car;
import com.bestqiang.easyfactory.RedCar;

/** * @author BestQiang */
public class FactoryA extends Factory {


    @Override
    public Phone phoneFactory(String type) {
        if(type.equals("huawei")) {
            print();
            return new HuaweiPhone();
        } if (type.equals("XiaomiPhone")) {
            print();
            return new XiaomiPhone();
        }
        return null;
    }

    @Override
    public Car carFactory(String type) {
        if(type.equals("red")) {
            print();
            return new RedCar();
        } if (type.equals("blue")) {
            print();
            return new BlueCar();
        }
        return null;
    }

    private void print() {
        System.out.println("A工厂出品");
    }
}

FactoryB:

package com.bestqiang.AFactory;

import com.bestqiang.easyfactory.BlueCar;
import com.bestqiang.easyfactory.Car;
import com.bestqiang.easyfactory.RedCar;

/** * @author BestQiang */
public class FactoryB extends Factory {

    @Override
    public Phone phoneFactory(String type) {
        if(type.equals("huawei")) {
            print();
            return new HuaweiPhone();
        } if (type.equals("XiaomiPhone")) {
            print();
            return new XiaomiPhone();
        }
        return null;
    }

    @Override
    public Car carFactory(String type) {
        if(type.equals("red")) {
            print();
            return new RedCar();
        } if(type.equals("blue")) {
            print();
            return new BlueCar();
        }
        return null;
    }

    private void print() {
        System.out.println("B工厂出品");
    }
}

package com.bestqiang.AFactory;

import com.bestqiang.easyfactory.Car;

/** * @author BestQiang */
public class Main {
    public static void main(String[] args) {
        Factory factory = new FactoryA();
        Car red = factory.carFactory("red");
        System.out.println(red);
    }
}

运行结果:

A工厂出品
Car{color='red', price='1000$', speed='999km/s'}

Process finished with exit code 0

三种工厂模式算是介绍完了,总结一下,

  • 简单工厂模式不能动态切换工厂,不依赖与抽象。
  • 工厂方法模式创建一个抽象的工厂类,子类进行继承实现,可以动态切换工厂,适合同一种类。
  • 抽象工厂模式把多个工厂隐含在里面,可以把相关的产品集合起来。是工厂模式的升级。
全部评论

相关推荐

微风不断:兄弟,你把四旋翼都做出来了那个挺难的吧
点赞 评论 收藏
分享
喜欢吃蛋糕仰泳鲈鱼是我的神:字节可以找个hr 给你挂了,再放池子捞
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务