设计模式
设计模式代表了最佳的实践,作为一个初入编程界的菜鸟,你可以不懂设计模式,但是作为一个开发经验3+的码农,设计模式就显得很重要了。
设计模式共有23种,分为三大类:创建型模式、结构型模式和行为型模式。
今天简单聊下创建型模式中的工厂模式与抽象工厂模式。
工厂模式
工厂模式是Java中最常用的设计模式之一,属于创建型模式,它提供了一种创建对象的最佳方式。
在工厂模式中,不直接创建一个对象,而是使用工厂来创建对象(使用一个共同的interface来指向该对象),避免将创建逻辑暴露给客户端。
实现:
创建一个Cup接口和它的实现类,然后定义一个CupFactory工厂类。CupFactory工厂类中通过不同的标识来判断创建哪种类型的Cup对象。
①创建Cup接口:
public interface Cup {
void color();
}
②创建Cup接口的实现:
@Slf4j
public class RedCup implements Cup{
@Override
public void color() {
log.info("my color is red");
}
}
@Slf4j
public class WhiteCup implements Cup{
@Override
public void color() {
log.info("my color is white");
}
}
@Slf4j
public class YellowCup implements Cup{
@Override
public void color() {
log.info("my color is yellow");
}
}
③创建工厂类:
public class CupFactory {
// 根据cup类型获取cup对象
public Cup getCup(String cupType) {
if (null == cupType) {
return null;
}
Cup cup = null;
switch (cupType) {
case "white":
cup = new WhiteCup();
break;
case "yellow":
cup = new YellowCup();
break;
case "red":
default:
cup = new RedCup();
break;
}
return cup;
}
}
④使用工厂创建Cup对象:
通过工厂来获取具体的对象,不需要知道对象的创建逻辑。
public class Demo {
public static void main(String[] args) {
// 创建一个cup 工厂
CupFactory factory = new CupFactory();
// 从工厂中获取redCup对象
Cup redCup = factory.getCup("red");
redCup.color();
// 从工厂中获取whiteCup对象
Cup whiteCup = factory.getCup("white");
whiteCup.color();
// 从工厂中获取yellowCup对象
Cup yellowCup = factory.getCup("yellow");
yellowCup.color();
}
}
日志打印如下:
INFO []2023-03-12 21:42:58.428[org.im.designpattern.RedCup][15][main][INFO]-my color is red
INFO []2023-03-12 21:42:58.433[org.im.designpattern.WhiteCup][15][main][INFO]-my color is white
INFO []2023-03-12 21:42:58.433[org.im.designpattern.YellowCup][15][main][INFO]-my color is yellow
工厂模式适用于不同条件下创建不同实例时。
优点:
- 调用者只需要知道具体的对象类型即可创建对象。
- 调用者不需要知道对象的具体创建逻辑。
- 可扩展性好,在增加一种对象时,只需要扩展工厂类即可。
不足:
每增加一种对象时,就需要增加一个具体实现类和扩展工厂类,使得系统中的类的数量成倍增加,增加了系统的复杂性,同时违背了开闭原则。
抽象工厂模式
抽象工厂模式中通过一个超级工厂,创建其他工厂,该超级工厂被称为工厂的工厂。
在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。
实现:
创建Cup和Vehicle两个接口,以及实现两个接口的实现类。然后创建抽象工厂AbstractFactory,以及两个继承抽象工厂的工厂类CupFactory和VehicleFactory,分别用于创建Cup和Vehicle对象。
① 创建Cup和Vehicle两个接口以及其实现类:
public interface Cup {
void color();
}
@Slf4j
public class RedCup implements Cup{
@Override
public void color() {
log.info("my color is red");
}
}
@Slf4j
public class WhiteCup implements Cup{
@Override
public void color() {
log.info("my color is white");
}
}
@Slf4j
public class YellowCup implements Cup{
@Override
public void color() {
log.info("my color is yellow");
}
}
public interface Vehicle {
void run();
}
@Slf4j
public class Car implements Vehicle{
@Override
public void run() {
log.info("car run");
}
}
@Slf4j
public class Train implements Vehicle{
@Override
public void run() {
log.info("train run");
}
}
@Slf4j
public class Bus implements Vehicle{
@Override
public void run() {
log.info("bus run");
}
}
②创建抽象工厂类以及工厂类:
public abstract class AbstractFactory {
// 创建Cup工厂
abstract Cup getCup(String cupType);
// 创建vehicle工厂
abstract Vehicle getVehicle(String vehicleType);
}
public class CupFactory extends AbstractFactory{
@Override
public Cup getCup(String cupType) {
if (null == cupType) {
return null;
}
Cup cup = null;
switch (cupType) {
case "white":
cup = new WhiteCup();
break;
case "yellow":
cup = new YellowCup();
break;
case "red":
default:
cup = new RedCup();
break;
}
return cup;
}
@Override
Vehicle getVehicle(String vehicle) {
return null;
}
}
public class VehicleFactory extends AbstractFactory{
@Override
public Vehicle getVehicle(String vehicleType) {
if (null == vehicleType) {
return null;
}
Vehicle vehicle = null;
switch (vehicleType) {
case "car":
vehicle = new Car();
break;
case "train":
vehicle = new Train();
break;
case "bus":
default:
vehicle = new Bus();
break;
}
return vehicle;
}
@Override
public Cup getCup(String cupType) {
return null;
}
}
③创建工厂生成器类,通过传递工厂类型,创建不同的工厂:
public class FactoryProducer {
// 根据 工厂类型,创建对应的工厂
public static AbstractFactory getFactory(String factoryType) {
if ("cup".equals(factoryType)) {
return new CupFactory();
} else if ("vehicle".equals(factoryType)) {
return new VehicleFactory();
}
return null;
}
}
④Demo中使用抽象工厂来创建工厂,以及工厂来创建具体对象:
public class Demo {
public static void main(String[] args) {
// 通过工厂生成器,根据工厂类型cup创建 cup 工厂
AbstractFactory cupFactory = FactoryProducer.getFactory("cup");
// 从工厂中获取redCup对象
Cup redCup = cupFactory.getCup("red");
redCup.color();
// 从工厂中获取whiteCup对象
Cup whiteCup = cupFactory.getCup("white");
whiteCup.color();
// 从工厂中获取yellowCup对象
Cup yellowCup = cupFactory.getCup("yellow");
yellowCup.color();
// 通过工厂生成器,根据工厂类型vehicle创建 vehicle 工厂
AbstractFactory vehicleFactory = FactoryProducer.getFactory("vehicle");
// 从工厂中获取car对象
Vehicle car = vehicleFactory.getVehicle("car");
car.run();
// 从工厂中获取train对象
Vehicle trainFactory = vehicleFactory.getVehicle("train");
trainFactory.run();
// 从工厂中获取bus对象
Vehicle busFactory = vehicleFactory.getVehicle("bus");
busFactory.run();
}
}
运行Demo,打印日志如下:
INFO []2023-03-13 21:31:59.111[org.im.designpattern.RedCup][15][main][INFO]-my color is red
INFO []2023-03-13 21:31:59.119[org.im.designpattern.WhiteCup][15][main][INFO]-my color is white
INFO []2023-03-13 21:31:59.121[org.im.designpattern.YellowCup][15][main][INFO]-my color is yellow
INFO []2023-03-13 21:31:59.129[org.im.designpattern.Car][15][main][INFO]-car run
INFO []2023-03-13 21:31:59.135[org.im.designpattern.Train][15][main][INFO]-train run
INFO []2023-03-13 21:31:59.142[org.im.designpattern.Bus][15][main][INFO]-bus run
抽象工厂模式适用于系统的产品有多个产品族,而系统只消费某一族的产品。
比如:1、QQ 换皮肤,一整套一起换。 2、生成不同操作系统的程序。
优点:
当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
不足:
产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。