工厂模式是我们最常用的设计模式之一,使用工厂方法替代new操作。工厂模式又分为三种,分别是简单工厂,工厂方法和抽象工厂。
定义一个工厂类,根据传入的参数来决定实例化哪个类:
public interface Mouse {
void sayHello();
}
public class DellMouse implements Mouse {
@Override
public void sayHello() {
System.out.println("你好,我是戴尔鼠标");
}
}
public class LenovoMouse implements Mouse {
@Override
public void sayHello() {
System.out.println("你好,我是联想鼠标");
}
}
// 鼠标工厂类,负责创建鼠标实例
public class MouseFactory {
public static Mouse createMouse(int type){
switch (type){
case 1:
return new DellMouse();
case 2:
return new LenovoMouse();
default:
return null;
}
}
}
来简单测试一下结果:
public static void main(String[] args) {
Mouse dell = MouseFactory.createMouse(1);
dell.sayHello();
Mouse lenovo = MouseFactory.createMouse(2);
lenovo.sayHello();
}
控制台输出的结果:
你好,我是戴尔鼠标
你好,我是联想鼠标
可以看到MouseFactory工厂类可以根据传入的type决定实例化哪个Mouse的实现类。
对创建对象的过程进行屏蔽,对客户端屏蔽细节。
缺点也是显而易见,假如创建对象的过程并不是简单的new LenovoMouse()或者new DellMouse()而是一大段初始化逻辑,又或者是Mouse的子类非常的多,简单工厂中createMouse方法将会变得非常臃肿。并且增加或删除对应的Mouse子类都需要去修改工厂类中的代码,违反了开闭原则。
工厂方法在简单工厂的基础上做了升级,将工厂类向下扩展,把创建对象的逻辑交由具体的子类工厂去完成。
在Mouse接口及其两个子类LenovoMouse和DellMouse不变的情况下,增加三个类:
// 工厂接口,创建逻辑交由具体子类去完成
public interface MouseFactory {
Mouse createMouse();
}
public class LenovoMouseFactory implements MouseFactory {
@Override
public Mouse createMouse() {
return new LenovoMouse();
}
}
public class DellMouseFactory implements MouseFactory {
@Override
public Mouse createMouse() {
return new DellMouse();
}
}
继续类测试一下结果:
public static void main(String[] args) {
MouseFactory dellMouseFactory = new DellMouseFactory();
Mouse dellMouse = dellMouseFactory.createMouse();
dellMouse.sayHello();
MouseFactory lenovoFactory = new LenovoMouseFactory();
Mouse lenovoMouse = lenovoFactory.createMouse();
lenovoMouse.sayHello();
}
控制台输出:
你好,我是戴尔鼠标
你好,我是联想鼠标
在简单工厂优点的基础上,工厂方法做了升级,符合开闭原则,单一责任原则,比如要增加一个Mouse的子类,那么只需要添加一个工厂子类去创建对应的Mouse子类即可,不需要改动工厂接口,并且每一种工厂只负责创建一个实例。
每添加一个Mouse的子类,就需要添加一个工厂类,项目中的类会变得非常多。
再者该工厂只能创建一类产品的创建,假如我们需要创建一系列产品 ,比如我想创建鼠标和键盘两种产品,工厂方法模式是做不到的。
继而,在工厂方法的基础上,衍生出了抽象方法模式。抽象工厂提供创建一系列相关或相互依赖对象的接口。
同样,在Mouse接口及其两个子类LenovoMouse和DellMouse不变的情况下做修改
// 键盘实例接口
public interface Keyboard {
void sayHello();
}
// 联想键盘
public class LenovoKeyboard implements Keyboard {
@Override
public void sayHello() {
System.out.println("你好,我是联想键盘");
}
}
// 戴尔键盘
public class DellKeyboard implements Keyboard {
@Override
public void sayHello() {
System.out.println("你好,我是戴尔键盘");
}
}
// 生产鼠标和键盘的工厂
public interface ComputerFactory {
/**
* 创建鼠标实例
* @return
*/
Mouse createMouse();
/**
* 创建键盘实例
* @return
*/
Keyboard createKeyboard();
}
// 联想鼠标和键盘工厂
public class LenovoComputerFactory implements ComputerFactory {
@Override
public Mouse createMouse() {
return new LenovoMouse();
}
@Override
public Keyboard createKeyboard() {
return new LenovoKeyboard();
}
}
// 戴尔鼠标和键盘工厂
public class DellComputerFactory implements ComputerFactory {
@Override
public Mouse createMouse() {
return new DellMouse();
}
@Override
public Keyboard createKeyboard() {
return new DellKeyboard();
}
}
继续测试:
public static void main(String[] args) {
ComputerFactory lenovoComputerFactory = new LenovoComputerFactory();
Keyboard lenovoKeyboard = lenovoComputerFactory.createKeyboard();
lenovoKeyboard.sayHello();
Mouse lenovoMouse = lenovoComputerFactory.createMouse();
lenovoMouse.sayHello();
ComputerFactory dellComputerFactory = new DellComputerFactory();
Mouse dellMouse = dellComputerFactory.createMouse();
dellMouse.sayHello();
Keyboard dellKeyboard = dellComputerFactory.createKeyboard();
dellKeyboard.sayHello();
}
控制台输出:
你好,我是联想键盘
你好,我是联想鼠标
你好,我是戴尔鼠标
你好,我是戴尔键盘
抽象工厂除了具有工厂方法的优点外,能够创建产品族,解决了工厂方法只支持生产一种产品的弊端。
抽象工厂依旧存在工厂方法的缺点,扩展起来类太多,关系负责,并且扩展一种产品的时候需要修改具体的工厂生产接口,违背了开闭原则。
抽象工厂:每个抽象产品派生多个具体的产品类,每个抽象工厂类派生出多个具体的工厂类,每个具体的工厂类负责一系列具体产品的创建
工厂方法:每个抽象产品派生多个具体的产品类,每个抽象工厂类派生出多个具体的工厂类,每个具体的工厂类负责一个具体产品的创建
可以根据不同的场景选择合适的工厂模式
原文:https://www.cnblogs.com/lgxblog/p/14460332.html