工厂模式
简单工厂模式
简单工厂模式将被使用方的创建过程封装到一个类中,这样就在使用方和被使用方之间做了一个缓冲,也就是将被使用方和被使用方进行解耦(降低了使用方和被使用方的耦合度),提高了软件的可扩展性、可维护性和可复用性。
案例:
UML类图:
消费者Consumer类:
/**
* 购买牙膏的消费者
*/
public class Consumer {
public static void main(String[] args) {
Shop shop = new Shop();
Toothpaste boughtToothpaste1 = shop.sellToothpaste("中华牌");
System.out.println("消费者买到了" + boughtToothpaste1);
System.out.println("================");
Toothpaste boughtToothpaste2 = shop.sellToothpaste("高露洁牌");
System.out.println("消费者买到了" + boughtToothpaste2);
}
}
商店Shop类:
/**
* 商店类用于用户消费者购买牙膏
*/
public class Shop {
/**
* 卖牙膏方法
*
* @param brand 牙膏品牌
* @return 牙膏对象
*/
public Toothpaste sellToothpaste(String brand) {
return SimpleFactory.createToothpaste(brand);
}
}
简单工厂SimpleFactory类:
/**
* 用于生产牙膏的简单工厂
*/
public class SimpleFactory {
/**
* 创建牙膏方法
*/
public static Toothpaste createToothpaste(String brand) {
Toothpaste toothpaste = null;
if ("中华牌".equals(brand)) {
toothpaste = new ZhongHuaToothpaste();
} else if ("高露洁牌".equals(brand)) {
toothpaste = new GaoLuJieToothpaste();
}
if (toothpaste != null) {
toothpaste.createPaste();
toothpaste.createShell();
toothpaste.pack();
}
return toothpaste;
}
}
牙膏抽象Toothpaste类:
/**
* 牙膏抽象类
*/
public abstract class Toothpaste {
protected String brand;
public void createPaste() {
System.out.println("产生了" + brand + "的膏体");
}
public void createShell() {
System.out.println("产生了" + brand + "的外壳");
}
public abstract void pack();
@Override
public String toString() {
return brand + "的牙膏";
}
}
高露洁牙膏GaoLuJieToothpaste实现类:
/**
* 高露洁牌牙膏
*/
public class GaoLuJieToothpaste extends Toothpaste {
public GaoLuJieToothpaste() {
this.brand = "高露洁牌";
}
@Override
public void pack() {
System.out.println("给" + brand + "牙膏进行了包装!");
}
}
中华牙膏ZhongHuaToothpaste实现类:
/**
* 中华牌牙膏
*/
public class ZhongHuaToothpaste extends Toothpaste {
public ZhongHuaToothpaste() {
this.brand = "中华牌";
}
@Override
public void pack() {
System.out.println("给" + brand + "牙膏进行了包装!");
}
}
总结:
-
简单工厂将使用方和被使用方进行解耦,提高了软件的可扩展性、可维护性和可复用性。
-
但是还是违背了开闭原则(OCP原则),如果后续要扩展新的功能,需要修改简单工厂的工厂类对象中创建对象的代码。
-
使用场景:简单工厂模式适用于具体类十分确定且固定的一类产品的创建,这样才能不太频繁的修改简单工程类去实现扩展。
工厂方法模式
将简单工厂中得到对象的方法写成一个抽象方法,也就是说在工厂类或者接口中不知道如何创建该对象,具体如何创建交给子类或者实现类去决定
案例:
UML类图:
消费者Consumer类:
/**
* 购买牙膏的消费者
*/
public class Consumer {
public static void main(String[] args) {
Shop shop = new Shop();
Toothpaste boughtToothpaste1 = shop.sellToothpaste(new ZhongHuaFactory());
System.out.println("消费者买到了" + boughtToothpaste1);
System.out.println("================");
Toothpaste boughtToothpaste2 = shop.sellToothpaste(new GaoLuJieFactory());
System.out.println("消费者买到了" + boughtToothpaste2);
}
}
商店Shop类:
/**
* 商店类用于用户消费者购买牙膏
*/
public class Shop {
/**
* 卖牙膏方法
* @param toothpasteFactory 牙膏品牌工厂
* @return 牙膏对象
*/
public Toothpaste sellToothpaste(ToothpasteFactory toothpasteFactory) {
return toothpasteFactory.createToothpaste();
}
}
牙膏工厂ToothpasteFactory接口类:
/**
* 用于生产牙膏的工厂
* 将简单工厂模式中的工厂类换成一个抽象类或者接口
* 并提供一个用户创建对象的抽象方法,也就是将创建对象
* 的过程下沉到实现类或者子类去实现。
*/
public interface ToothpasteFactory {
/**
* 创建牙膏方法(这个方法就是工厂方法)
* @return
*/
Toothpaste createToothpaste();
}
中华牙膏工厂ZhongHuaFactory类:
/**
* 中华牌工厂类
*/
public class ZhongHuaFactory implements ToothpasteFactory {
@Override
public Toothpaste createToothpaste() {
Toothpaste toothpaste = new ZhongHuaToothpaste();
toothpaste.createPaste();
toothpaste.createShell();
toothpaste.pack();
return toothpaste;
}
}
高露洁牙膏工厂GaoLuJieFactory类:
/**
* 高露洁牌工厂类
*/
public class GaoLuJieFactory implements ToothpasteFactory{
@Override
public Toothpaste createToothpaste() {
Toothpaste toothpaste = new GaoLuJieToothpaste();
toothpaste.createPaste();
toothpaste.createShell();
toothpaste.pack();
return toothpaste;
}
}
牙膏Toothpaste抽象类:
/**
* 牙膏抽象类
*/
public abstract class Toothpaste {
protected String brand;
public void createPaste() {
System.out.println("产生了" + brand + "的膏体");
}
public void createShell() {
System.out.println("产生了" + brand + "的外壳");
}
public abstract void pack();
@Override
public String toString() {
return brand + "的牙膏";
}
}
高露洁牙膏GaoLuJieToothpaste类:
/**
* 高露洁牌牙膏
*/
public class GaoLuJieToothpaste extends Toothpaste {
public GaoLuJieToothpaste() {
this.brand = "高露洁牌";
}
@Override
public void pack() {
System.out.println("给" + brand + "牙膏进行了包装!");
}
}
中华牙膏ZhongHuaToothpaste类:
/**
* 中华牌牙膏
*/
public class ZhongHuaToothpaste extends Toothpaste {
public ZhongHuaToothpaste() {
this.brand = "中华牌";
}
@Override
public void pack() {
System.out.println("给" + brand + "牙膏进行了包装!");
}
}
总结:
-
将简单工厂中得到对象的方法写成一个抽象方法,其具体的类提供不同的工厂类来继承,实现类各自实现自己的工厂父类,这样遵循了开闭原则,我们只需要对其进行扩展,不需要修改任何原有类代码。
-
但这种方式会随着子工厂类和其实现类的增多而增加类的复杂度。
-
推荐使用这种方式。
抽象工厂模式
提供一个创建一系列相关或者相互依赖的对象的工厂接口,而无需指定它们具体的类。其作用是产生一个产品系列或者是产品簇。
UML类图:
消费者Consumer类:/**
* 购买刷牙工具的消费者
*/
public class Consumer {
public static void main(String[] args) {
Shop shop = new Shop();
String boughtToothbrushingUtil = shop.sellToothbrushUtils(new ZhongHuaFactory());
System.out.println("消费者买到了" + boughtToothbrushingUtil);
System.out.println("================");
String boughtToothbrushingUtil2 = shop.sellToothbrushUtils(new GaoLuJieFactory());
System.out.println("消费者买到了" + boughtToothbrushingUtil2);
}
}
商店Shop类:
/**
* 商店类用于用户消费者购买刷牙工具
*/
public class Shop {
/**
* 卖刷牙工具方法
*
* @param toothBrushingFactory 刷牙工具的品牌工厂
* @return 刷牙工具对象
*/
public String sellToothbrushUtils(ToothBrushingFactory toothBrushingFactory) {
Toothpaste toothpaste = toothBrushingFactory.createToothpaste();
Toothbrush toothbrush = toothBrushingFactory.createToothbrush();
return toothpaste + "和" + toothbrush;
}
}
工厂接口ToothBrushingFactory:
/**
* 用于生产刷牙工具的工厂
* 工厂方法模式产生的产品都是一个类或接口的子类实例,
* 抽象工厂模式产生的产品是多个接口或抽象类的子类实例。
*/
public interface ToothBrushingFactory {
/**
* 创建牙膏方法
*
* @return
*/
Toothpaste createToothpaste();
/**
* 创建牙刷方法
*
* @return
*/
Toothbrush createToothbrush();
}
中华牌工厂ZhongHuaFactory类:
/**
* 中华牌工厂类
*/
public class ZhongHuaFactory implements ToothBrushingFactory {
@Override
public Toothpaste createToothpaste() {
Toothpaste toothpaste = new ZhongHuaToothpaste();
toothpaste.createPaste();
toothpaste.createShell();
toothpaste.pack();
return toothpaste;
}
@Override
public Toothbrush createToothbrush() {
Toothbrush toothbrush = new ZhongHuaToothbrush();
toothbrush.createHandle();
toothbrush.createHair();
toothbrush.pack();
return toothbrush;
}
}
高露洁牌工厂类
/**
* 高露洁工厂类
*/
public class GaoLuJieFactory implements ToothBrushingFactory {
@Override
public Toothpaste createToothpaste() {
Toothpaste toothpaste = new GaoLuJieToothpaste();
toothpaste.createPaste();
toothpaste.createShell();
toothpaste.pack();
return toothpaste;
}
@Override
public Toothbrush createToothbrush() {
Toothbrush toothbrush = new GaoLuJieToothbrush();
toothbrush.createHandle();
toothbrush.createHair();
toothbrush.pack();
return toothbrush;
}
}
牙刷Toothbrush抽象类:
/**
* 牙刷抽象类
*/
public abstract class Toothbrush {
protected String brand;
public void createHair() {
System.out.println("产生了" + brand + "的牙刷毛");
}
public void createHandle() {
System.out.println("产生了" + brand + "的手柄");
}
public abstract void pack();
@Override
public String toString() {
return brand + "的牙刷";
}
}
中华牌牙刷ZhongHuaToothbrush类:
/**
* 中华牌牙刷
*/
public class ZhongHuaToothbrush extends Toothbrush {
public ZhongHuaToothbrush() {
this.brand = "中华牌";
}
@Override
public void pack() {
System.out.println("给" + brand + "牙刷进行了组装!");
}
}
高露洁牌牙刷GaoLuJieToothbrush类:
/**
* 高露洁牌牙刷
*/
public class GaoLuJieToothbrush extends Toothbrush {
public GaoLuJieToothbrush() {
this.brand = "高露洁牌";
}
@Override
public void pack() {
System.out.println("给" + brand + "牙刷进行了组装!");
}
}
牙膏Toothpaste抽象类:
/**
* 牙膏抽象类
*/
public abstract class Toothpaste {
protected String brand;
public void createPaste() {
System.out.println("产生了" + brand + "的膏体");
}
public void createShell() {
System.out.println("产生了" + brand + "的外壳");
}
public abstract void pack();
@Override
public String toString() {
return brand + "的牙膏";
}
}
中华牌牙膏ZhongHuaToothpaste类:
/**
* 中华牌牙膏
*/
public class ZhongHuaToothpaste extends Toothpaste {
public ZhongHuaToothpaste() {
this.brand = "中华牌";
}
@Override
public void pack() {
System.out.println("给" + brand + "牙膏进行了包装!");
}
}
高露洁牌牙膏GaoLuJieToothpaste类:
/**
* 高露洁牌牙膏
*/
public class GaoLuJieToothpaste extends Toothpaste {
public GaoLuJieToothpaste() {
this.brand = "高露洁牌";
}
@Override
public void pack() {
System.out.println("给" + brand + "牙膏进行了包装!");
}
}
总结:
-
工厂方法模式产生的产品都是一个类或接口的子类实例,抽象工厂模式产生的产品是多个接口或抽象类的子类实例。
-
这种方式其实也可以单独的把它看做一个设计模式(包含在23种设计模式之中)。
-
当关心的是一个产品簇对象的创建时,推荐使用此方式。