设计模式之工厂模式
定义:
工厂模式是java中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
工厂模式主要是为创建对象提供过度接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。
核心本质:
(1)实例化对象,用工厂方法代替new操作
(2)将选择实现类,创建对象统一管理和控制,从而将调用者跟我们的实现类解耦
工厂模式可以根据抽象程度的不同分为三种
(1)简单工厂模式(也叫静态工厂模式)
(2)工厂方法模式(也叫多行性工厂)
(3)抽象工厂模式(也叫工具箱)
简单工厂模式:
实质由一个工厂类根据传入的参数,动态决定应该创建哪一个产品的实例。简单工厂模式的创建目标是所有创建的对象都是充当这个角色的某个具体类的实例。(用来生产同一等级结构中的任意产品,对于增加新的产品,需要修改已有的代码)
代码如下:
public interface Car {
void run();
}
public class Audi implements Car {
@Override
public void run() {
System.out.println("奥迪再跑!");
}
}
public class Byd implements Car {
@Override
public void run() {
System.out.println("比亚迪再跑!");
}
}
public class CarFactory {
public static Car createCar(String type) {
if("奥迪".equals(type)){
return new Audi();
}else if("比亚迪".equals(type)){
return new Byd();
}else{
return null;
}
}
}
public class Test01 {
public static void main(String[] args) {
Car car1 = CarFactory.createCar("奥迪");
Car car2 = CarFactory.createCar("比亚迪");
car1.run();
car2.run();
}
}
优点:简单工厂模式也叫静态工厂模式,就是工厂类一般是使用静态方法,通过接受的参数的不同来返回不同的对象实例
缺点:对于增加的新产品无能为力!不修改代码的话,是无法扩展的。
工厂方法模式:
工厂方法是粒度很小的设计模式,因为模式的表现只是一个抽象的方法,提前定义用于创建对象的接口,让子类决定实例化具体的某一个类,即在工厂和产品中间增加接口,工厂不在负责产品的创建,由接口针对不同条件返回具体的类实例,由具体的类实例去实现。(用来生产同一等级结构中的固定产品,支持增加任意产品)
代码如下:
public interface Car {
void run();
}
public class Byd implements Car {
@Override
public void run() {
System.out.println("比亚迪再跑!");
}
}
public class Audi implements Car {
@Override
public void run() {
System.out.println("奥迪再跑!");
}
}
public interface CarFactory {
Car createCar();
}
public class BydFactory implements CarFactory {
@Override
public Car createCar() {
return new Byd();
}
}
public class AudiFactory implements CarFactory {
@Override
public Car createCar() {
return new Audi();
}
}
public class Client {
public static void main(String[] args) {
Car c1 = new AudiFactory().createCar();
Car c2 = new BydFactory().createCar();
c1.run();
c2.run();
}
}
优点:工厂方法模式和简单工厂模式最大的不同在于,简单工厂模式只有一个(对于一个项目或者一个独立模块而言)工厂类,而工厂方法模式有一组实现了相同接口的工厂类。
缺点:为了避免简单工厂模式的缺点,不完全满足OCP(开闭原则)
抽象工厂模式:
当有多个抽象角色时使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体的情况下,创建对个产品对象,它有多个抽象产品类,每个抽象产品类可以派生出多个具体的产品类,一个抽象工厂类,可以派生出多个具体工厂类,每个具体工厂类可以创建多个具体的产品类的实例。(用来生产不同产品族的全部产品,对于增加新的产品,无能为力,支持增加产品族)
代码如下:
public interface Engine {
void run();
void start();
}
class LuxuryEngine implements Engine{
@Override
public void run() {
System.out.println("转的快!");
}
@Override
public void start() {
System.out.println("启动快!可以自动启停!");
}
}
class LowEngine implements Engine{
@Override
public void run() {
System.out.println("转的慢!");
}
@Override
public void start() {
System.out.println("启动慢!");
}
}
public interface Seat {
void massage();
}
class LuxurySeat implements Seat {
@Override
public void massage() {
System.out.println("可以自动按摩!");
}
}
class LowSeat implements Seat {
@Override
public void massage() {
System.out.println("不能按摩!");
}
}
public interface Tyre {
void revolve();
}
class LuxuryTyre implements Tyre {
@Override
public void revolve() {
System.out.println("旋转不磨损!");
}
}
class LowTyre implements Tyre {
@Override
public void revolve() {
System.out.println("旋转磨损快!");
}
}
public interface CarFactory {
Engine createEngine();
Seat createSeat();
Tyre createTyre();
}
public class LowCarFactory implements CarFactory {
@Override
public Engine createEngine() {
return new LowEngine();
}
@Override
public Seat createSeat() {
return new LowSeat();
}
@Override
public Tyre createTyre() {
return new LowTyre();
}
}
public class LuxuryCarFactory implements CarFactory {
@Override
public Engine createEngine() {
return new LuxuryEngine();
}
@Override
public Seat createSeat() {
return new LuxurySeat();
}
@Override
public Tyre createTyre() {
return new LuxuryTyre();
}
}
public class Test {
public static void main(String[] args) {
CarFactory factory=new LowCarFactory();
Engine c = factory.createEngine();
c.run();
c.start();
}
}
优点:用来生产不同产品族的全部产品,对于增加新的产品,无能为力,支持增加产品族
在有多个业务品种,业务分类时,通过抽象工厂模式产生需要的对象是一种非常好的解决方式。
总结工厂模式的优缺点:
优点:
(1)一个调用者想创建一个对象,只要知道其名称就可以了,降低了耦合度。
(2)扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。使得代码结构更加清晰。
(3)屏蔽产品的具体实现,调用者只关心产品的接口。
缺点:
每次增加一个产品时,都需要增加一个具体类和对象实现工厂(这里可以使用反射机制来避免),使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。所以对于简单对象来说,使用工厂模式反而增加了复杂度。
工厂模式的适用场景:
(1) 一个对象拥有很多子类。
(2) 创建某个对象时需要进行许多额外的操作。
(3) 系统后期需要经常扩展,它把对象实例化的任务交由实现类完成,扩展性好。