1 简单工厂模式
定义一个工厂类,根据传入的参数的值不同返回不同的实例
特点:被创建的实例具有共同的父类或接口
例子:客户端想要获取不同的鼠标类别对象
1.鼠标接口以及实现类
public interface Mouse {
void sayHi();
}
public class DellMouse implements Mouse{
public void sayHi() {
System.out.println("我是戴尔鼠标");
}
}
public class HpMouse implements Mouse{
public void sayHi() {
System.out.println("我是惠普鼠标");
}
}
2.生产鼠标的工厂类:根据不同的参数返回不同类型的鼠标对象
//简单工厂
public class MouseFactory {
public static Mouse createMouse(int type)
{
if(type==1)
return new DellMouse();
else if(type==2)
return new HpMouse();
else
return new DellMouse();
}
}
3.客户端通过工厂类获取鼠标对象
public static void main(String[] args) {
Mouse mouse=MouseFactory.createMouse(1);
mouse.sayHi();
}
简单工厂隐藏了对象创建的细节,客户端不需要自己去创建实例,而只需要告诉工厂,需要创建的对象类别即可。
使用场景:1.需要创建的对象较少 2.客户端不关心对象的创建过程
优点:可以对创建的对象进行“加工”,对客户端隐藏相关细节
缺点:因创建逻辑复杂或创建对象过多而造成代码臃肿;新增、删除子类均会违反开闭原则
开闭原则:一个软件实体,应该对扩展开放,对修改关闭。即应该通过扩展来实现变化,而不是通过修改已有的代码来实现变化
拿上面的例子来说:
如果想要新增一个鼠标类别,这时需要新增一个类,新增一个类这个操作是符合开闭原则的,因为新增一个类并不会影响到原来的接口和实现类。
但是对于工厂类来说,就需要修改createMouse方法,此时便违背了开闭原则,因为我们修改了原有的代码。
2 工厂方法模式
定义一个用于创建对象的接口,让子类决定实例化哪一个类
对类的实例化延迟到其子类
例子同上,但是工厂方法模式是做法是让特定类型的工厂类生产特定类型的鼠标
相比简单工厂模式直接定义MouseFactory类来创建不同类型的鼠标,工厂方法模式则是定义一个MouseFactory接口,将创建不同类型鼠标的实现下沉到MouseFactory不同的工厂子类中。
1.工厂接口
public interface MouseFactory {
Mouse createMouse();
}
2.生成不同鼠标的工厂子类
public class DellMouseFactory implements MouseFactory {
public Mouse createMouse() {
return new DellMouse();
}
}
public class HpMouseFactory implements MouseFactory {
public Mouse createMouse() {
return new HpMouse();
}
}
3.客户端通过具体工厂类获取鼠标对象
public class Main {
public static void main(String[] args) {
MouseFactory mouseFactory=new DellMouseFactory();
Mouse mouse=mouseFactory.createMouse();
mouse.sayHi();
}
}
优点:遵循开闭原则(如果新增一个鼠标类,那么就新增一个工厂类,并不会需要在原有的代码中修改。)
对客户端隐藏对象的创建细节;遵循单一职责
缺点:添加子类的时候还需要添加一个工厂类;只支持同一类产品的创建。(鼠标工厂类只支持鼠标对象的创建)
3 抽象工厂模式
提供一个创建一系列相关或相互依赖对象的接口
抽象工厂模式侧重的是同一产品族;工厂方法模式更加侧重于同一产品等级
例子:不同工厂生产不同公司的键盘和鼠标套装
1.添加键盘接口和实现类
public interface Keyboard {
void sayHello();
}
public class DellKeyboard implements Keyboard {
public void sayHello() {
System.out.println("我是戴尔键盘");
}
}
public class HpKeyboard implements Keyboard {
public void sayHello() {
System.out.println("我是惠普键盘");
}
}
2.工厂接口
public interface ComputerFactory {
Mouse createMouse();
Keyboard createKeyboard();
}
3.工厂实现类
public class DellComputerFactory implements ComputerFactory {
public Mouse createMouse() {
return new DellMouse();
}
public Keyboard createKeyboard() {
return new DellKeyboard();
}
}
public class HpComputerFactory implements ComputerFactory {
public Mouse createMouse() {
return new HpMouse();
}
public Keyboard createKeyboard() {
return new HpKeyboard();
}
}
4.客户端通过工厂获取一系列产品
public class Main {
public static void main(String[] args) {
ComputerFactory cf = new DellComputerFactory();
Mouse mouse=cf.createMouse();
Keyboard keyboard=cf.createKeyboard();
mouse.sayHi();
keyboard.sayHello();
}
}
抽象工厂模式与工厂方法模式对比:
工厂方法模式:每个抽象产品派生多个具体产品类,每个抽象工厂类派生多个具体工厂类,每个具体工厂类负责一个具体产品的实例创建
抽象工厂模式:每个抽象产品派生多个具体产品类,每个抽象工厂类派生多个具体工厂类,每个具体工厂类负责一系列具体产品的实例创建
优点:解决了工厂模式只支持生产一种产品的弊端。新增一个产品族,只需要增加一个新的具体工厂,不需要修改代码,即满足了开闭原则。
缺点:添加新产品时依旧违背开闭原则,增加系统的复杂度。如果产品族新增了一款产品,比如主板,那么每一个工厂类都需要新增一个方法。