是什么?
工厂模式是一种创建型设计模式,它提供了一种创建对象的接口,但允许子类决定实例化的类。工厂模式遵循开闭原则,即对扩展开放,对修改关闭。
在Java中,工厂模式通常有三种形式:简单工厂模式、工厂方法模式和抽象工厂模式。
-
简单工厂模式:在简单工厂模式中,一个工厂类负责创建多个不同类型的对象。这种模式的开闭原则体现在新增一种产品类型时,只需要修改工厂类即可,而不需要修改客户端代码。
-
工厂方法模式:工厂方法模式通过定义一个创建对象的接口,但将实际创建工作推迟到子类中。这样,每个子类都可以根据需要创建适合自己需求的对象。这符合开闭原则,因为新增的产品类型只需要添加对应的工厂子类,而不需要修改已有的代码。
-
抽象工厂模式:抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。这种模式允许系统在不修改具体工厂的情况下引入新的产品,符合开闭原则的要求。
总的来说,工厂模式通过将对象的创建和使用分离,使得系统更容易扩展新的产品类型,而不需要修改已有的代码,从而符合开闭原则的设计原则。
关于开闭原则的补充:
对于扩展开放(Open for Extension):工厂模式允许系统在不修改已有代码的情况下引入新的产品类型。当需要添加新的产品类型时,只需要创建新的具体产品类和对应的工厂类,而不需要修改已有的代码。这种灵活性使得系统能够轻松地适应变化和扩展,符合开放的特性。对于修改关闭(Closed for Modification):工厂模式通过将对象的创建和使用分离,使得客户端代码不依*赖于具体产品类,而是依赖于抽象产品类和工厂类。这意味着当需要修改已有的产品类型或工厂类时,不需要*修改客户端代码,只需要修改对应的具体工厂类或具体产品类即可。这种设计原则使得系统的稳定性得到保
障,符合关闭的特性。
简单工厂模式
新建一个“鼠标接口”,声明一个方法
package demo.pattern.factory.entity;
public interface Mouse {
void sayHi();
}
再新建两个鼠标类,实现接口,他们分别是戴尔鼠标和惠普鼠标
package demo.pattern.factory.entity;
public class DellMouse implements Mouse {
@Override
public void sayHi() {
System.out.println("我是戴尔鼠标");
}
}
package demo.pattern.factory.entity;
import demo.annotation.TestAnnotation;
public class HpMouse implements Mouse {
@Override
public void sayHi() {
System.out.println("我是惠普鼠标");
}
}
这时我们就可以创建一个鼠标工厂
public class MouseFactory {
public static Mouse createMouse(int type){
switch (type) {
case 0: return new DellMouse();
case 1: return new HpMouse();
default: return new DellMouse();
}
}
public static void main(String[] args) {
Mouse mouse = MouseFactory.createMouse(1);
mouse.sayHi();
}
}
以上是简单工厂模式的实例,简单工厂隐藏了对象创建的细节,客户端不需要自己创建实例,只需要告知需要什么品牌的鼠标。
简单工厂模式的适用场景:
1、需要创建的对象少;
2、客户端不关心对象的创建过程;
简单工厂模式的优缺点:
优点:可以对创建的对象进行“加工”,对客户端隐藏相关细节
缺点:1、因创建逻辑复杂或出啊关键对象过多而造成代码臃肿;
2、新增、删除子类均会违反开闭原则
例如,对现有的工厂,添加一个新的产品类,“联想鼠标”
package demo.pattern.factory.entity;
public class LenovoMouse implements Mouse {
@Override
public void sayHi() {
System.out.println("我是联想鼠标");
}
}
它扩展了“鼠标接口”,并未对接口和其他产品类产生修改,但是对于工厂类
public class MouseFactory {
public static Mouse createMouse(int type){
switch (type) {
case 0: return new DellMouse();
case 1: return new HpMouse();
case 2: return new LenovoMouse();
default: return new DellMouse();
}
}
public static void main(String[] args) {
Mouse mouse = MouseFactory.createMouse(1);
mouse.sayHi();
}
}
需要新添加一钟情况,修改了原有代码,违反了开闭原则
工厂方法模式
定义一个用于创建对象的接口,让子类决定实例化哪一个类
对类的实例化延迟到其子类
创建一个“鼠标工厂接口”,声明一个方法“生产鼠标”
package demo.pattern.factory.method;
import demo.pattern.factory.entity.Mouse;
public interface MouseFactory {
Mouse createMouse();
}
接下来,新建三个实体类实现“鼠标工厂接口”:
package demo.pattern.factory.method;
public class DellMouseFactory implements MouseFactory {
@Override
public Mouse createMouse() {
return new DellMouse();
}
}
package demo.pattern.factory.method;
public class HpMouseFactory implements MouseFactory {
@Override
public Mouse createMouse() {
return new HpMouse();
}
}
package demo.pattern.factory.method;
public class LenovoMouseFactory implements MouseFactory{
@Override
public Mouse createMouse() {
return new LenovoMouse();
}
}
此时新增产品类,只需新对应工厂类,工厂方法模式不会违反开闭原则,同时也隐藏了创建具体实例,且具有单一职责。
工厂方法模式,是简单工厂模式的进一步抽象和扩展,保留了简单工厂的封装优点,让扩展变得简单,让继承可行,增加了多态的体现。
但是随着新产品类的不断增加,对应工厂类也随之增加,系统类的个数成倍增加,增加了系统的复杂度,还需要创造同等数量的controller类,使代码变得臃肿。添加子类时“拖家带口”
抽象工厂模式
抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口;
抽象工厂模式侧重的是同一产品族,工厂方法模式更侧重同一产品等级
假设,产品“鼠标”“键盘”需要成套购买。
创建“键盘接口”
package demo.pattern.factory.entity;
public interface Keyboard {
void sayHello();
}
创建实体类,实现就“键盘接口”
package demo.pattern.factory.entity;
public class DellKeyboard implements Keyboard {
@Override
public void sayHello() {
System.out.println("我是戴尔键盘");
}
}
package demo.pattern.factory.entity;
public class HpKeyboard implements Keyboard {
@Override
public void sayHello() {
System.out.println("我是惠普键盘");
}
}
package demo.pattern.factory.entity;
public class LenovoKeyboard implements Keyboard {
@Override
public void sayHello() {
System.out.println("我是联想键盘");
}
}
创建“电脑工厂接口”,声明生产“鼠标”“键盘”的方法
package demo.pattern.factory.abstractf;
import demo.pattern.factory.entity.Keyboard;
import demo.pattern.factory.entity.Mouse;
public interface ComputerFactory {
Mouse createMouse();
Keyboard createKeyboard();
}
创建戴尔,惠普,联想的对应工厂类,实现电脑工厂接口
package demo.pattern.factory.abstractf;
public class DellComputerFactory implements ComputerFactory {
@Override
public Mouse createMouse() {
return new DellMouse();
}
@Override
public Keyboard createKeyboard() {
return new DellKeyboard();
}
}
package demo.pattern.factory.abstractf;
public class HpComputerFactory implements ComputerFactory {
@Override
public Mouse createMouse() {
return new HpMouse();
}
@Override
public Keyboard createKeyboard() {
return new HpKeyboard();
}
}
package demo.pattern.factory.abstractf;
public class LenovoComputerFactory implements ComputerFactory {
@Override
public Mouse createMouse() {
return new LenovoMouse();
}
@Override
public Keyboard createKeyboard() {
return new LenovoKeyboard();
}
}
之后我们就可以来生产对应对应品牌的“键鼠套装”
package demo.pattern.factory.abstractf;
public class AbstractFactoryDemo {
public static void main(String[] args) {
ComputerFactory cf = new HpComputerFactory();
Mouse mouse = cf.createMouse();
Keyboard keyboard = cf.createKeyboard();
mouse.sayHi();
keyboard.sayHello();
}
}
抽象工厂模式可以生产多个等级的产品,解决了工厂模式只支持一种产品的弊端。
新增一个产品族时,只需新增加一个新的具体工厂,不需要修改代码。
但是,增加新产品时,依旧违反开闭原则,增加系统复杂度。
spring解决这个问题,依靠的是工厂模式和反射机制结合的I Spring IOC容器来实现Bean的创建。