描述
工厂模式用以封装复杂的实例初始化过程,供外部统一调用
简单工厂(静态工厂)
如果对象创建逻辑简单且一致,可以使用简单工厂。传入想要生成的实例类型
public class HumanFactory {
public static <T> T getInstance(Class<T> c) {
try {
return (T) Class.forName(c.getName()).getDeclaredConstructor().newInstance();
} catch (Exception e) {
throw new RuntimeException("生成对象异常", e);
}
}
}
工厂方法模式
多种类型产品初始化逻辑不一致时,可以采用不同工厂实例来初始化对应类型的产品
由于每种产品定义了对应的工厂类,因此工厂方法不需要类型参数就非常明确需要创建的实例
- 声明工厂抽象定义
public abstract class AbstractProductFactory {
public abstract Product createProduct();
}
- 声明产品抽象定义
public interface Product {
String getName();
default void description() {
System.out.println("产品名称:" + getName());
}
}
- 定义具体产品
public class Apple implements Product {
@Override
public String getName() {
return "苹果";
}
}
public class Banana implements Product {
@Override
public String getName() {
return "香蕉";
}
}
- 定义产品对应的工厂
public class AppleFactory extends AbstractProductFactory {
public Product createProduct() {
// 苹果其他初始化逻辑
return new Apple();
}
}
public class BananaFactory extends AbstractProductFactory {
public Product createProduct() {
// 香蕉其他初始化逻辑
return new Banana();
}
}
- 使用
public static void main(String[] args) {
AbstractProductFactory appleFactory = new AppleFactory();
Product product = appleFactory.createProduct();
product.description();
AbstractProductFactory bananaFactory = new BananaFactory();
Product banana = bananaFactory.createProduct();
banana.description();
}
抽象工厂
以上工厂方法,一个产品就需要一个工厂类。
如果产品本身就有一些共通的地方,我们可以将产品划分到同一个工厂的不同产品线,这些产品的生产可以共用一些资源。
比如,我的产品都分为大、中、小三种分类。分别进行不同的加工
- 声明抽象水果
public interface Fruit {
String getName();
String getSize();
default void description() {
System.out.println("产品名称:" + getSize() + getName());
}
}
- 声明具体水果
public class BigApple implements Fruit {
@Override
public String getName() {
return "苹果";
}
@Override
public String getSize() {
return "大号";
}
}
public class MiddleApple implements Fruit {
@Override
public String getName() {
return "苹果";
}
@Override
public String getSize() {
return "中号";
}
}
public class SmallApple implements Fruit {
@Override
public String getName() {
return "苹果";
}
@Override
public String getSize() {
return "小号";
}
}
public class BigBanana implements Fruit {
@Override
public String getName() {
return "香蕉";
}
@Override
public String getSize() {
return "大号";
}
}
public class MiddleBanana implements Fruit {
@Override
public String getName() {
return "香蕉";
}
@Override
public String getSize() {
return "中号";
}
}
public class SmallBanana implements Fruit {
@Override
public String getName() {
return "香蕉";
}
@Override
public String getSize() {
return "小号";
}
}
- 声明抽象工厂
public abstract class AbstractFruitFactory {
abstract Fruit bigFruit();
abstract Fruit middleFruit();
abstract Fruit smallFruit();
}
- 定义具体工厂
public class AppleFruitFactory extends AbstractFruitFactory{
@Override
Fruit bigFruit() {
return new BigApple();
}
@Override
Fruit middleFruit() {
return new MiddleApple();
}
@Override
Fruit smallFruit() {
return new SmallApple();
}
}
public class BananaFruitFactory extends AbstractFruitFactory {
@Override
Fruit bigFruit() {
return new BigBanana();
}
@Override
Fruit middleFruit() {
return new MiddleBanana();
}
@Override
Fruit smallFruit() {
return new SmallBanana();
}
}
增加工厂管理类
当抽象工厂的子类扩展时,调用方需要和各个子类工厂交互,在一定程度上违反了迪米特法则。
我们可以将工厂子类交由工厂管理类进行管理,调用方只需要和这个管理类交互即可
public final class FruitFactoryManager {
private static Map<String, AbstractFruitFactory> register = new HashMap<>();
static {
register.put("apple", new AppleFruitFactory());
register.put("banana", new BananaFruitFactory());
}
public static AbstractFruitFactory getFactory(String factoryCode) {
return register.get(factoryCode);
}
}
使用
public class Sample {
public static void main(String[] args) {
AbstractFruitFactory appleFactory = new AppleFruitFactory();
Fruit smallApple = appleFactory.smallFruit();
smallApple.description();
Fruit middleApple = appleFactory.middleFruit();
middleApple.description();
Fruit bigApple = appleFactory.bigFruit();
bigApple.description();
AbstractFruitFactory bananaFactory = new BananaFruitFactory();
Fruit smallBanana = bananaFactory.smallFruit();
smallBanana.description();
Fruit middleBanana = bananaFactory.middleFruit();
middleBanana.description();
Fruit bigBanana = bananaFactory.bigFruit();
bigBanana.description();
}
}