工厂模式的引入
有一天,小明同学准备去买笔记本电脑,他到了商城发现有两款电脑他特别喜欢,一款是 Macbook Pro, 另一款是 SurfacePro。
根据以上的场景,类图可以如下表示:
代码:
interface Computer{
void printComputer();
}
class MacbookProComputer implements Computer {
public void printComputer() {
System.out.println("This is a MacbookPro");
}
}
class SurfaceBookComputer implements Computer {
public void printComputer() {
System.out.println("This is a SurfaceBook");
}
}
public class Client {
public void buyComputer(Computer computer) {
computer.printComputer();
}
public static void main(String[] args) {
Client client = new Client();
client.buyComputer(new MacbookProComputer());
}
}
那现在假如说小明又看上了一款外星人(Alienware)笔记本,我们就不得不返回客户端去修改代码,让客户端支持Alienware笔记本。那么,如何将实例化具体类的代码从客户端中抽离,或者封装起来,使它们不会干扰应用的其他部分呢?
简单工厂模式
简单工厂模式:专门定义一个类用来创建其他类的实例,被创建的实例通常都具有共同的父类。
将类的实例化交给工厂,易于解耦
范例:
import java.util.Scanner;
import java.util.Stack;
interface Computer{
void printComputer();
}
class MacbookProComputer implements Computer {
public void printComputer() {
System.out.println("This is a MacbookPro");
}
}
class SurfaceBookComputer implements Computer {
public void printComputer() {
System.out.println("This is a SurfaceBook");
}
}
class ComputerFactory{
public static Computer getInstance(String type){
if(type==null) return null;
switch (type){
case "MacbookPro":return new MacbookProComputer();
case "SurfaceBook":return new SurfaceBookComputer();
}
return null;
}
}
public class Client {
public void buyComputer(Computer computer) {
computer.printComputer();
}
public static void main(String[] args) {
Client client=new Client();
Scanner cin=new Scanner(System.in);
String type=cin.nextLine();
Computer computer=null;
if((computer=ComputerFactory.getInstance(type))!=null){
client.buyComputer(computer);
}else{
System.out.println("对不起,没有您要的电脑...");
}
}
}
以上就是简单工厂模式:
一个抽象产品类
具体产品类
一个工厂
优缺点
优点:
简单易于实现
把类的实例化交给工厂易于解耦
缺点:
添加具体产品需要修改工厂违反了开放封闭原则(对扩展开放,对修改关闭)
工厂方法模式
工厂方法模式:定义一个用来创建对象的接口,让子类决定实例化哪一个类,让子类决定实例化延迟到子类。
interface Computer{
void printComputer();
}
class MacbookProComputer implements Computer {
public void printComputer() {
System.out.println("This is a MacbookPro");
}
}
class SurfaceBookComputer implements Computer {
public void printComputer() {
System.out.println("This is a SurfaceBook");
}
}
interface ComputerFactory {
Computer createComputer();
}
class MsFactory implements ComputerFactory {
public Computer createComputer() {
return new SurfaceBookComputer();
}
}
class AppleFactory implements ComputerFactory {
public Computer createComputer() {
return new MacbookProComputer();
}
}
public class Client {
public void buyComputer(Computer computer) {
computer.printComputer();
}
public static void main(String[] args) {
Client client=new Client();
client.buyComputer(new MsFactory().createComputer());
}
}
概要:
一个抽象产品类
多个具体产品类
一个抽象工厂
多个具体工厂-每一个具体产品对呀一个具体工厂
对比简单工厂模式和工厂方法模式:
对于简单工厂模式而言,创建对象的逻辑判断放在了工厂类中,客户不感知具体的类,但是其违背了开闭原则,如果要增加新的具体类,就必须修改工厂类。
对于工厂方法模式而言,是通过扩展来新增具体类的,符合开闭原则,但是在客户端就必须要感知到具体的工厂
类,也就是将判断逻辑由简单工厂的工厂类挪到客户端。
优缺点
优点:
- 降低了代码耦合度,对象的生成交给子类去完成
- 实现了开放封闭原则 - 每次添加子产品 不需要修改原有代码
缺点:- 增加了代码量,每个具体产品都需要一个具体工厂
- 当增加抽象产品 也就是添加一个其他产品族 需要修改工厂 违背OCP
抽象工厂类
抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
如果说,这时候负责该工厂的产品经理说要生产新的一类产品操作系统 Mac Os 和 Windows 8,这时候就引申出了抽象工厂模式。
interface Computer {
void printComputer();
}
class MacbookProComputer implements Computer {
public void printComputer() {
System.out.println("This is a MacbookPro");
}
}
class SurfaceBookComputer implements Computer {
public void printComputer() {
System.out.println("This is a SurfaceBook");
}
}
interface OperatingSystem {
void printSystem();
}
概要
class MacOsSystem implements OperatingSystem {
public void printSystem() {
System.out.println("This is a mac os");
}
}
class Windows8System implements OperatingSystem {
public void printSystem() {
System.out.println("This is a window 8");
}
}
interface ProductionFactory {
Computer createComputer();
OperatingSystem createSystem();
}
class AppleFactory implements ProductionFactory {
public Computer createComputer() {
return new MacbookProComputer();
}
public OperatingSystem createSystem() {
return new MacOsSystem();
}
}
class MsFactory implements ProductionFactory {
public Computer createComputer() {
return new SurfaceBookComputer();
}
public OperatingSystem createSystem() {
return new Windows8System();
}
}
public class Client {
public void buyComputer(Computer computer) {
computer.printComputer();
}
public void use(OperatingSystem s) {
s.printSystem();
}
public static void main(String[] args) {
Client client = new Client();
ProductionFactory factory = new AppleFactory();
Computer computer = factory.createComputer();
OperatingSystem system = factory.createSystem();
client.buyComputer(computer);
client.use(system);
}
}
概要:
多个抽象产品类
具体产品类
抽象工厂 类- 声明(一组)返回抽象产品的方法
具体工厂 类- 生成(一组)具体产品
优缺点
优点:
- 代码解耦
- 实现多个产品族(相关联产品组成的家族),而工厂方法模式的单个产品,可以满足更多的生产需求
- 很好的满足OCP开放封闭原则
- 抽象工厂模式中我们可以定义实现不止一个接口,一个工厂也可以生成不止一个产品类 对于复杂对象的生产相当灵活易扩展
缺点:
1.扩展产品族相当麻烦 而且扩展产品族会违反OCP,因为要修改所有的工厂
2.由于抽象工厂模式是工厂方法模式的扩展 总体的来说 很笨重
总结:
简单工厂模式:最大的特点就是工厂内有具体逻辑去判断生成什么产品,将类的实例化交给工厂,这样当我们需要什么产品只需要修改工厂的调用而不需要去修改客户端,对于客户端来说降低了与具体产品的依赖
工厂方法模式:简单工厂的扩展,将工厂和实例化产品对象分离出来,如果要添加一个产品种类的时候不需要去修改工厂类,只要添加对应的产品子类就可以实现了。
抽象工厂模式是进一步扩展了工厂方法模式,它把原先的工厂方法模式中只能有一个抽象产品不能添加产品族的缺点克服了,抽象工厂模式不仅仅遵循了OCP原则,而且可以添加更多产品(抽象产品),具体工厂也不仅仅可以生成单一产品,而是生成一组产品,抽象工厂也是声明一组产品,对应扩展更加灵活,但是要是扩展族系就会很笨重。
工厂设计模式的作用:
解耦
增强扩展性
增强代码的封装性和可读性