1、简述
工厂模式包括简单工厂模式、工厂方法模式和抽象工厂模式,属于创建型模式。
2、不使用工厂模式
(1)类图分析
一个接口Computer,接口有两个实现类HP和Apple,同时有一个测试类Client。不使用工厂模式时,在Client中直接通过new操作符类创建HP和Apple类的实例。
(2)代码展示
Computer接口:
package com.factory;
public interface Computer {
void compute();
}
HP类:
package com.factory;
public class HP implements Computer {
@Override
public void compute() {
// TODO Auto-generated method stub
System.out.println("This is HP PC");
}
}
Apple类:
package com.factory;
public class Apple implements Computer {
@Override
public void compute() {
// TODO Auto-generated method stub
System.out.println("This is Apple PC");
}
}
测试类:
package com.factory;
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
//不适用工厂模式常见多个类
Apple apple = new Apple();
HP hp = new HP();
apple.compute();
hp.compute();
}
}
(3)运行结果:
This is Apple PC
This is HP PC
(4)缺点和不足:
对于测试类Client来说调用者而言,需要知道HP和Car类的细节,尤其是构造方法的细节,比如需要知道构造方法的参数类型、参数个数等。当有许多Conputer接口的实现类时候,对于Client来说,需要知道的类细节更多,给Client带来较大压力。
3、使用工厂模式
(1)简单工厂模式
(a)类图分析
在上述实现方式的基础上,在类的实现结构中增加一层ComputerFactory,此类的作用是返回HP或者Apple等类的实例对象,具体创建并返回哪一个类的实例在ComputerFactory中通过分支语句来实现。最终的Client测试类仅仅需要调用ComputerFactory中的方法,并传入必要的参数即可。简言之,就是工厂类一般是使用静态方法,通过接受的参数的不同来返回不同的对象实例。
(b)代码展示
Computer接口、HP类、Apple类与(1)中相同
ComputerFactory类:
方式一:
package com.factory;
public class ComputerFactory {
public static Computer createComputer(String computer) {
if("HP".equals(computer)) {
return new HP();
}else if("Apple".equals(computer)){
return new Apple();
}else {
return null;
}
}
}
方式二:
package com.factory;
public class ComputerFactory {
public static Computer createHP() {
return new HP();
}
public static Computer createApple() {
return new Apple();
}
}
测试类:
测试一(对应于方式一):
package com.factory;
public class Client {
public static void main(String[] args) {
//使用简单工厂模式
Computer hp = ComputerFactory.createComputer("HP");
Computer apple = ComputerFactory.createComputer("Apple");
apple.compute();
hp.compute();
}
}
测试二(对应于方式二):
package com.factory;
public class Client {
public static void main(String[] args) {
//使用简单工厂模式
Computer hp = ComputerFactory.createHP();
Computer apple = ComputerFactory.createApple();
apple.compute();
hp.compute();
}
}
(c)运行结果
This is Apple PC
This is HP PC
(d)缺点和不足:
如果需要增加新的Computer类的话,需要修改ComputerFactory内部的代码。这违反了类设计的开闭原则,开闭原则就是说类对拓展开放,对修改关闭。所以简单工厂模式在面对需要增加新的类的时候会违反开闭原则。
(2)工厂方法模式
(a)类图分析
简单工厂模式中,只有一个公共的工厂类ComputerFactory,所以当需要增加商品的时候,需要修改ComputerFactory,导致违反了开闭原则。所以为每个商品类定义一个特定的工厂类,此处为HP类设置定义一个HPFactory工厂类,为Apple类定义一个AppleFactory类。这样的话看,当需要增加一个新的产品类的时候,不需要对原有的工厂类进行修改,只需要增加一个新的工厂类即可。同时,为了各个工厂的统一性,定义一个工厂接口Factory,然后各个具体产品工厂XXXFactory实现接口Factory,从而统一了接口中的方法。
(b)代码展示
Computer类:
package com.factorymethod;
public interface Computer {
void compute();
}
HP类:
package com.factorymethod;
public class HP implements Computer{
@Override
public void compute() {
// TODO Auto-generated method stub
System.out.println("HP");
}
}
Apple类:
package com.factorymethod;
public class Apple implements Computer {
@Override
public void compute() {
// TODO Auto-generated method stub
System.out.println("Apple");
}
}
Factory类:
package com.factorymethod;
public interface Factory {
Computer createrComputer();
}
HPFactory类:
package com.factorymethod;
public class HPFactory implements Factory {
@Override
public Computer createrComputer() {
// TODO Auto-generated method stub
return new HP();
}
}
AppleFactory类:
package com.factorymethod;
public class AppleFactory implements Factory {
@Override
public Computer createrComputer() {
// TODO Auto-generated method stub
return (Computer) new Apple();
}
}
测试类Client:
package com.factorymethod;
public class Client {
public static void main(String args[]) {
Computer hp = new HPFactory().createrComputer();
Computer apple = new AppleFactory().createrComputer();
hp.compute();
apple.compute();
}
}
(c)运行结果
HP
Apple
(d)缺点与不足
相比于简单工厂模式,工厂方法模式避免了破坏开闭原则,但是由于为每个类都创建了一个工厂类,导致了类的数目增加。
(3)抽象工厂模式
(a)概述
抽象工厂模式是工厂方法模式的升级版本,适用于有多个业务种类和等级的情形,可以用来生产不同产品族的全部产品,对于增加新的产品,无能为力;支持增加产品族 。
抽象工厂模式中,有一系列产品接口,每个产品接口都有多个实现类,在工厂类中通过选择产品接口的不同实现类可以生产出不同种类、不同等级的产品,从而形成了产品族。例如,每个产品接口都有两个实现类GoodXXX和PoorXXX,工厂类中如果选择所有的GoodXXX实现类,将生产出Good产品,工厂类中如果选择所有的PoorXXX实现类,将生产出Poor产品,从而最终形成了两个产品线。
(b)类图分析
在此案例中,有三个产品接口CPU、Monitor和Keyboard,同时每个产品接口有两个实现类,分别为GoodCPU和PoorCPU、GoodMonitor和PoorMonitor、GoodKeyboar和PoorKeyboard,其中GoodFactory工厂选择GoodCPU、GoodMonitor、GoodKeyboar创建产品,PoorFactory工厂选择PoorCPU、PoorMonitor、PoorKeyboard创建产品,从而形成了Good和Poor产品两个产品线。
(c)代码展示
CPU类:
package abstractfactory;
public interface CPU {
void say();
}
class GoodCPU implements CPU{
@Override
public void say() {
// TODO Auto-generated method stub
System.out.println("I am is Good CPU");
}
}
class PoorCPU implements CPU{
@Override
public void say() {
// TODO Auto-generated method stub
System.out.println("I am is Poor CPU");
}
}
Monitor类:
package abstractfactory;
public interface Monitor {
void say();
}
class GoodMonitor implements Monitor{
@Override
public void say() {
// TODO Auto-generated method stub
System.out.println("I am Good Monitor");
}
}
class PoorMonitor implements Monitor{
@Override
public void say() {
// TODO Auto-generated method stub
System.out.println("I am Poor Monitor");
}
}
Keyboard类:
package abstractfactory;
public interface Keyboard {
void say();
}
class GoodKeyboard implements Keyboard{
@Override
public void say() {
// TODO Auto-generated method stub
System.out.println("I am Good Keyboard");
}
}
class PoorKeyboard implements Keyboard{
@Override
public void say() {
// TODO Auto-generated method stub
System.out.println("I am Poor Keyboard");
}
}
Factory接口:
package abstractfactory;
public interface Factory {
CPU createCPU();
Monitor createMonitor();
Keyboard createKeyboard();
}
GoodFactory类:
package abstractfactory;
public class GoodFactory implements Factory {
@Override
public CPU createCPU() {
// TODO Auto-generated method stub
return new GoodCPU();
}
@Override
public Monitor createMonitor() {
// TODO Auto-generated method stub
return new GoodMonitor();
}
@Override
public Keyboard createKeyboard() {
// TODO Auto-generated method stub
return new GoodKeyboard();
}
}
PoorFactory类:
package abstractfactory;
public class PoorFactory implements Factory {
@Override
public CPU createCPU() {
// TODO Auto-generated method stub
return new PoorCPU();
}
@Override
public Monitor createMonitor() {
// TODO Auto-generated method stub
return new PoorMonitor();
}
@Override
public Keyboard createKeyboard() {
// TODO Auto-generated method stub
return new PoorKeyboard();
}
}
Client测试类:
package abstractfactory;
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
Factory gf = new GoodFactory();
CPU gcpu = gf.createCPU();
Monitor gmonitor = gf.createMonitor();
Keyboard gkeyboard = gf.createKeyboard();
gcpu.say();
gmonitor.say();
gkeyboard.say();
System.out.println("----------------------------------");
Factory pf = new PoorFactory();
CPU pcpu = pf.createCPU();
Monitor pmonitor = pf.createMonitor();
Keyboard pkeyboard = pf.createKeyboard();
pcpu.say();
pmonitor.say();
pkeyboard.say();
}
}
运行结果;
I am is Good CPU
I am Good Monitor
I am Good Keyboard
----------------------------------
I am is Poor CPU
I am Poor Monitor
I am Poor Keyboard
(d)缺点和不足
抽象工厂莫斯可以增加产品族,但是不可以增加产品。