SimpleFactory
说到工厂,我们应该能想到,造汽车的有汽车工厂,造轮船的有轮船工厂,映射到Java中,造对象的就应该有对象工厂,比如说我想要买一辆车,那我只需要去汽车工厂(先不去4S店)里面告诉它什么品牌的汽车,具体参数,给钱提车就完了,我并不需要了解汽车是如何造出来的,也就是屏蔽了造车的细节,这样的好处就是对于买家来说,简单方便,用户体验大大提升,对于卖家来说我厂生产汽车的具体细节不会外露。
需求:
用户提出要圆形、三角形、菱形等等。
解决方案1:
public void m1() {
// 用户需要圆,自己new一个
Circle circle = new Circle();
// 用户需要三角形,自己new一个
Triangle triangle = new Triangle();
}
解决方案2:
可以使用简单工厂的模式,只需要将工厂暴露给调用方,调用方给出自己想要的形状就可以了,因为所有的设计模式都是面向接口编程,所以接口是少不了的。
定义一个Shape接口
/**
* Description: 所有图形都有的公共属性,定义成抽象类也可以,接口也可
* @From www.zhangjianbing.com
* @Author 70KG
* @Date 2019/3/7
* @Since v1.0
*/
public interface Shape {
void draw();
}
Shape接口的实现类CricleShape
/**
* Description: 圆形实例
* @From www.zhangjianbing.com
* @Author 70KG
* @Date 2019/3/7
* @Since v1.0
*/
public class CircleShape implements Shape {
public CircleShape() {
System.out.println("圆形创建出来。");
}
@Override
public void draw() {
System.out.println("画出一个圆形。");
}
}
Shape接口的实现类Triangle
/**
* Description: 三角形实例
* @From www.zhangjianbing.com
* @Author 70KG
* @Date 2019/3/7
* @Since v1.0
*/
public class TriangleShape implements Shape {
public TriangleShape() {
System.out.println("三角形创建出来。");
}
@Override
public void draw() {
System.out.println("画出一个三角形");
}
}
简单工厂类,对外暴露方法
/**
* Description: 简单工厂类
* @From www.zhangjianbing.com
* @Author 70KG
* @Date 2019/3/7
* @Since v1.0
*/
public class ShapeFactory {
/**
* 1. 简单工厂模式对外屏蔽了对象的创建细节,需要什么对象直接从工厂获取。
* 2. 将获取对象的方法声明成静态的,由工厂类,向外提供服务。
*/
public static Shape getShape(String shapeName) {
Shape shape = null;
if (null != shapeName && !"".equals(shapeName)) {
if ("circle".equalsIgnoreCase(shapeName)) {
shape = new CircleShape();
} else if ("triangle".equalsIgnoreCase(shapeName)) {
shape = new TriangleShape();
}
}
return shape;
}
}
测试类
在调用方只需要给工厂提供想要的形状即可,不必关心形状是如何来的。
/**
* Description: 简单工厂模式测试用例
* @From www.zhangjianbing.com
* @Author 70KG
* @Date 2019/3/7
* @Since v1.0
*/
public class Test01 {
@Test
public void m1() {
Shape circle = ShapeFactory.getShape("circle");
circle.draw();
}
}
简单工厂,根本来说不属于23中设计模式中的一种,但工厂方法模式和抽象工厂模式都是由它演变来的,它的缺点:系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,有可能造成工厂逻辑过于复杂,违背了OCP原则。
FactoryMethod
还是上面的汽车例子,简单工厂类中维护了创建不同汽车的逻辑,比如说包括宝马,奔驰,奥迪,但后续需求越来越多,又增添了长城,马自达,大众等等品牌,那么这个工厂类的创建逻辑会越来越多,现实中,宝马有宝马自己的工厂,奔驰也有奔驰自己的工厂,映射到Java中,不同的类,应该有各自的工厂,这样的目的就是为了维护扩展方便,同时遵循了OCP原则。
设计模式是基于接口的,首先要有一个汽车的接口Car,它用来规定汽车的公共功能:
/**
* Description: 所有汽车的公共接口
* @From www.zhangjianbing.com
* @Author 70KG
* @Date 2019/3/11
* @Since v1.0
*/
public interface Car {
/**
* car在跑。
*/
void running();
}
然后是具体品牌汽车的实例:
宝马:
/**
* Description:
* @From www.zhangjianbing.com
* @Author 70KG
* @Date 2019/3/11
* @Since v1.0
*/
public class BaoMa implements Car {
@Override
public void running() {
System.out.println("宝马飞驰。");
}
}
奔驰:
/**
* Description:
* @From www.zhangjianbing.com
* @Author 70KG
* @Date 2019/3/11
* @Since v1.0
*/
public class BenChi implements Car {
@Override
public void running() {
System.out.println("奔驰奔跑。");
}
}
然后是各自品牌的工厂,在创建各自工厂之前,最好加一层汽车工厂接口,目的是用多态来返回不同的工厂,使代码更加灵活。
汽车工厂接口:
/**
* Description:
* @From www.zhangjianbing.com
* @Author 70KG
* @Date 2019/3/11
* @Since v1.0
*/
public interface CarFactory {
Car createCar();
}
各自的汽车工厂类:
宝马工厂:
/**
* Description:
* @From www.zhangjianbing.com
* @Author 70KG
* @Date 2019/3/11
* @Since v1.0
*/
public class BaoMaFactory implements CarFactory {
@Override
public Car createCar() {
System.out.println("宝马工厂生产汽车。");
return new BaoMa();
}
}
奔驰工厂:
/**
* Description:
* @From www.zhangjianbing.com
* @Author 70KG
* @Date 2019/3/11
* @Since v1.0
*/
public class BenChiFactory implements CarFactory {
@Override
public Car createCar() {
System.out.println("奔驰工厂生产汽车。");
return new BenChi();
}
}
测试类:
/**
* Description:
* @From www.zhangjianbing.com
* @Author 70KG
* @Date 2019/3/11
* @Since v1.0
*/
public class Test01 {
@Test
public void m1() {
// 1. 先获取宝马车的工厂,如果想改奔驰的,仅改动一行代码即可。
CarFactory carFactory = new BaoMaFactory();
// 2. 利用工厂来制造汽车
Car car = carFactory.createCar();
car.running();
}
}
工厂方法模式就很利于扩展,且不需要改动原来的代码,不管增加多少个品牌,只需要增加对应的工厂,以及实例就好了。
适用场景:
- 客户端不需要知道它所创建的对象的类。例子中我们不知道每个汽车具体叫什么名,只知道创建它的工厂名就完成了创建过程。
- 客户端可以通过子类来指定创建对应的对象。
AbstractFactory
抽象工厂的局限性比较大,并且它不符合OCP原则,工厂方法模式是创建一个对象,而抽象工厂它可以创建一组对象,这是和工厂方法模式最大的不同点。上述汽车的例子,假如汽车生产出来,出厂之前,我还需要给汽车做一个包装保养的服务,比如宝马有宝马的包装保养,奔驰有奔驰的包装保养,那是不是应该再创建一个专门做保养的工厂呢,肯定不是,抽象工厂的作用就是将汽车的生产、保养,以及后续的任务都做到一起,秉承一条龙服务,包括汽车的生产,包装,保养,维修等。
首先定义基本接口:
- 汽车公共接口Car:
/**
* Description:
* @From www.zhangjianbing.com
* @Author 70KG
* @Date 2019/3/11
* @Since v1.0
*/
public interface Car {
/**
* car在跑。
*/
void running();
}
- 汽车维修服务接口CarFix:
/**
* Description:
* @From www.zhangjianbing.com
* @Author 70KG
* @Date 2019/3/11
* @Since v1.0
*/
public interface CarFix {
/**
* 汽车维修服务
*/
void carFix(Car car);
}
- 汽车包装服务接口CarPack:
/**
* Description:
* @From www.zhangjianbing.com
* @Author 70KG
* @Date 2019/3/11
* @Since v1.0
*/
public interface CarPack {
/**
* 汽车包装服务
*/
void carPack(Car car);
}
三个接口的实现类:
- Car类
宝马BaoMa:
/**
* Description:
* @From www.zhangjianbing.com
* @Author 70KG
* @Date 2019/3/11
* @Since v1.0
*/
public class BaoMa implements Car {
@Override
public void running() {
System.out.println("宝马飞驰。");
}
}
奔驰BenChi:
/**
* Description:
* @From www.zhangjianbing.com
* @Author 70KG
* @Date 2019/3/11
* @Since v1.0
*/
public class BenChi implements Car {
@Override
public void running() {
System.out.println("奔驰奔跑。");
}
}
- 维修类CarFixService:
/**
* Description:
* @From www.zhangjianbing.com
* @Author 70KG
* @Date 2019/3/11
* @Since v1.0
*/
public class CarFixService implements CarFix {
@Override
public void carFix(Car car) {
System.out.println(car.getClass() + "在维修。");
}
}
- 包装类CarPackService:
/**
* Description:
* @From www.zhangjianbing.com
* @Author 70KG
* @Date 2019/3/11
* @Since v1.0
*/
public class CarPackService implements CarPack {
@Override
public void carPack(Car car) {
System.out.println(car.getClass() + "精美包装。");
}
}
抽象工厂:
抽象工厂中提供了此工厂所有的服务以及功能,包括汽车生产、包装、维修等。
/**
* Description:
* @From www.zhangjianbing.com
* @Author 70KG
* @Date 2019/3/11
* @Since v1.0
*/
public interface AbstractFactory {
/**
* 汽车创造
*/
Car createCar();
/**
* 汽车修理服务
*/
CarFix carFix(Car car);
/**
* 汽车包装服务
*/
CarPack carPack(Car car);
}
具体的汽车工厂:
奔驰工厂BenChiFactory:
/**
* Description:
* @From www.zhangjianbing.com
* @Author 70KG
* @Date 2019/3/11
* @Since v1.0
*/
public class BenChiFactory implements AbstractFactory {
@Override
public Car createCar() {
return new BenChi();
}
@Override
public CarFix carFix(Car car) {
return new CarFixService();
}
@Override
public CarPack carPack(Car car) {
return new CarPackService();
}
}
宝马工厂BaoMaFactory:
/**
* Description:
* @From www.zhangjianbing.com
* @Author 70KG
* @Date 2019/3/11
* @Since v1.0
*/
public class BaoMaFactory implements AbstractFactory {
@Override
public Car createCar() {
return new BaoMa();
}
@Override
public CarFix carFix(Car car) {
return new CarFixService();
}
@Override
public CarPack carPack(Car car) {
return new CarPackService();
}
}
测试类:
/**
* Description:
* @From www.zhangjianbing.com
* @Author 70KG
* @Date 2019/3/11
* @Since v1.0
*/
public class Test01 {
@Test
public void m1() {
// 1. 先按名字获取工厂
AbstractFactory factory = new BenChiFactory();
// 2. 生产车
Car car = factory.createCar();
// 3. 包装车
CarPack carPack = factory.carPack(car);
carPack.carPack(car);
// 4. 上路
car.running();
// 5. 修理车
CarFix carFix = factory.carFix(car);
carFix.carFix(car);
// -- 以上全部都是由工厂来完成。
}
}
测试结果:
生产奔驰。
BenChi精美包装。
奔驰奔跑。
BenChi在维修。
抽象工厂适用场景:
- 和工厂方法一样客户端不需要知道它所创建的对象的类。
- 需要一组对象共同完成某种功能时。并且可能存在多组对象完成不同功能的情况。
- 系统结构稳定,不会频繁的增加对象。(因为一旦增加就需要修改原有代码,不符合开闭原则)
网友评论