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
三种工厂模式算是介绍完了,总结一下,
- 简单工厂模式不能动态切换工厂,不依赖与抽象。
- 工厂方法模式创建一个抽象的工厂类,子类进行继承实现,可以动态切换工厂,适合同一种类。
- 抽象工厂模式把多个工厂隐含在里面,可以把相关的产品集合起来。是工厂模式的升级。