设计模式之工厂模式

来源:互联网 发布:国外域名交易平台 编辑:程序博客网 时间:2024/06/06 12:56

        从一个例子开始介绍工厂模式。

        假设有一个生产Windows系统兼容机和Mac电脑的工厂,里面有一个装配员,当客户需要一台电脑时,告诉装配员是需要Windows系统电脑还是Mac系统电脑,工厂就会生产一台电脑并且交由装配员装配,然后交给客户。

首先需要一个电脑的接口:

public interface Computer {public void selfIntroduce(); // 打印电脑信息}
Windows电脑的实现类:

public class Windows implements Computer {@Overridepublic void selfIntroduce() {System.out.println("Windows已生产.");}}
Mac电脑的实现类:
public class Mac implements Computer {@Overridepublic void selfIntroduce() {System.out.println("Mac已生产.");}}
装配员实现类:

public class Boxer {public Computer boxComputer(String computer) {if(computer.equals("Mac")) {return new Mac();} else {return new Windows();}}}
测试类:

public class Main {public static void main(String[] args) {Boxer boxer = new Boxer();Computer computer1 = boxer.boxComputer("Mac"); // 客户要求生产一台Mac系统电脑computer1.selfIntroduce();Computer computer2 = boxer.boxComputer("Windows"); // 客户要求生产一台Windows系统电脑computer2.selfIntroduce();}}
可以看到输出:

Mac已生产.

Windows已生产.

这就是简单工厂模式,客户希望得到哪台类型的电脑,只需要告诉装配员,工厂就会生产一台对应的电脑出来,用法很简单。但是简单工厂模式不符合开闭原则(对扩展开放,对修改关闭),当用户希望得到一台linux电脑时,需要增加Linux电脑实现类:

public class Linux implements Computer {@Overridepublic void selfIntroduce() {System.out.println("Linux已生产.");}}
再增加装配员的功能:

public class Boxer {public Computer boxComputer(String computer) {if(computer.equals("Mac")) {return new Mac();} else if(computer.equals("Linux")) {return new Linux();} else {return new Windows();}}}
测试:

public class Main {public static void main(String[] args) {Boxer boxer = new Boxer();Computer computer1 = boxer.boxComputer("Mac");computer1.selfIntroduce();Computer computer2 = boxer.boxComputer("Windows");computer2.selfIntroduce();Computer computer3 = boxer.boxComputer("Linux"); // 客户要求再生产一台Linux系统电脑computer3.selfIntroduce();}}
输出:

Mac已生产.

Windows已生产.

Linux已生产.

如果还有更多系统类型的电脑,如Ubuntu、RedHat、朝鲜的红星,如果再细一点,Windows需要生产Win98、Win7、Win10等等,这样,需要装配员实现类代码会急剧增加,严重违反开闭原则。如果继续采用上面的方式,整个需求的实现将是个噩梦。

要实现用户的新需求,整个工厂方法应该如何来写呢?

这里,我们采用抽象工厂模式。

抽象工厂模式与简单工厂模式最大的区别在于,抽象工厂模式将产生产品类和角色类,同一个系列的产品将由对应的产品类和角色类组成的工厂来生产,也就是说抽象工厂模式是由许多个工厂流水线组成。假如客户需要Windows系统电脑,工厂j就会交由Windows装配员来完成并将产品交给客户,这就是抽象工厂模式。

开始完成客户的新需求:

装配员的接口:

public interface Boxer {public Computer assembledComputer();}
Windows电脑装配员实现类:

public class WindowsBoxer implements Boxer {@Overridepublic Computer assembledComputer() {return new Windows();}}
Mac电脑装配员实现类:

public class MacBoxer implements Boxer {@Overridepublic Computer assembledComputer() {return new Mac();}}
Linux电脑装配员实现类:
public class LinuxBoxer implements Boxer {@Overridepublic Computer assembledComputer() {return new Linux();}}
测试:

public class Main {public static void main(String[] args) {Boxer boxer1 = new WindowsBoxer();Computer computer1 = boxer1.assembledComputer();computer1.selfIntroduce();Boxer boxer2 = new MacBoxer();Computer computer2 = boxer2.assembledComputer();computer2.selfIntroduce();Boxer boxer3 = new LinuxBoxer();Computer computer3 = boxer3.assembledComputer();computer3.selfIntroduce();}}
输出:

Windows已生产.

Mac已生产.

Linux已生产.

可以看到,采用抽象工厂模式后,整个需求实现的代码量增大了,但是结构上更加清晰,并且符合开闭原则。

假如客户又有新的需求,需要的电脑包装里面装好电源适配器,那我们可以继续用抽象工厂模式的方式来扩展。

增加电源适配器接口:

public interface Adapter {public void assembled();}
Windows电源适配器实现类:

public class WindowsAdapter implements Adapter {@Overridepublic void assembled() {System.out.println("Windows电源适配器已装配.");}}
Mac和Linux电源适配器同理,此处略。

修改Windows实现类:

public class Windows implements Computer {private Adapter windowsAdapter;public Windows(Adapter windowsAdapter) {this.windowsAdapter = windowsAdapter;}@Overridepublic void selfIntroduce() {System.out.println("Windows已生产.");windowsAdapter.assembled();}}
同理修改Mac和Linux实现类。

测试:

public class Main {public static void main(String[] args) {Boxer boxer1 = new WindowsBoxer();Computer computer1 = boxer1.assembledComputer();computer1.selfIntroduce();Boxer boxer2 = new MacBoxer();Computer computer2 = boxer2.assembledComputer();computer2.selfIntroduce();Boxer boxer3 = new LinuxBoxer();Computer computer3 = boxer3.assembledComputer();computer3.selfIntroduce();}}

输出:

Windows已生产.

Windows电源适配器已装配.

Mac已生产.

Mac电源适配器已装配.

Linux已生产.

Linux电源适配器已装配.

新的需求将抽象工厂类的产品和对应角色组装在了一起,也可以理解为工厂里面包含一个小的工厂,具体的产品交由小的工厂来实现,这样在产品和角色比较多的场合是非常适合的。

0 0
原创粉丝点击