前言
之前在网上看了很多关于工厂模式的文章,之前看完就觉得懂了,可之后又忘了,上周把实习结束了,匆匆告别,匆匆回校。很棒的实习经历,有空再写。回校后打算理一遍设计模式,自己实现一遍,当是加深一下记忆,为之后正式的工作打好基础。先写写工厂模式。
工厂模式主要分为三种,简单工厂模式,工厂模式,以及抽象工厂模式。说到工厂模式,其实我觉得在类和类之间的解耦起到了比较关键的作用,还是要在适当的场景下使用适当的设计模式。
以实际的例子讲讲这三种设计模式吧,我觉得例子是最能加强记忆的。
简单工厂模式
“民以食为天”,就举食物相关的例子。
简单起见,为食物抽象出三个属性:成本,售价,名字。创建抽象类:
public abstract class Food {
private int price;
private int cost;
private String name;
public Food() {
}
public Food(int price, int cost, String name) {
this.price = price;
this.cost = cost;
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public int getCost() {
return cost;
}
public void setCost(int cost) {
this.cost = cost;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Food{" +
"price=" + price +
", cost=" + cost +
", name='" + name + '\'' +
'}';
}
}
设想了两个类继承Food类,一个是“炒饭”,一个是“面条”。
FriedRice:
public class FriedRice extends Food {
public FriedRice() {
this(100, 20, "FriedRice");
}
public FriedRice(int price, int cost, String name) {
super(price, cost, name);
}
@Override
public String toString() {
return "FriedRice{" +
"price=" + super.getPrice() +
", cost=" + super.getCost() +
", name='" + super.getName() + '\'' +
'}';
}
}
Noodles:
public class Noodles extends Food {
public Noodles() {
this(50, 10, "Noodles");
}
public Noodles(int price, int cost, String name) {
super(price, cost, name);
}
@Override
public String toString() {
return "Noodles{" +
"price=" + super.getPrice() +
", cost=" + super.getCost() +
", name='" + super.getName() + '\'' +
'}';
}
}
对于简单工厂模式而言,只是提供了一个生产对象的工厂,看网上大部分通过switch或者if进行实例化对象,这里我是用了反射去实现,感觉代码的可维护性会更好,当然,反射的效率是个问题,factory中添加了缓存进行了适当的优化。
public class FoodFactory {
private ConcurrentHashMap<String, Class> classCache;
FoodFactory() {
classCache = new ConcurrentHashMap<>();
}
public Object getClz(String clzName) throws Exception {
Object obj;
if (classCache.get(clzName) != null) {
obj = classCache.get(clzName).newInstance();
} else {
obj = Class.forName(clzName).newInstance();
}
return obj;
}
}
测试类:
public class Main {
public static void main(String[] args) {
FoodFactory foodFactory = new FoodFactory();
String foodName = "com.dmc.DesignPatterns.simpleFactory.FriedRice";
Object food = chooseFood(foodName, foodFactory);
System.out.println(food.toString());
}
public static Object chooseFood(String foodName, FoodFactory foodFactory) {
Object food = null;
try {
food = foodFactory.getClz(foodName);
} catch (Exception e) {
e.printStackTrace();
}
return food;
}
}
写完觉得简单工厂模式还是觉得单个工厂难以维护,而且在效率上有一定的局限,结构也不是很清晰。就比如你一个车间要去加工所有类型的产品,给人的感觉就是“乱”。
工厂模式
在简单工厂模式的基础上,抽象出“FoodFactory”的接口,每一种食物都交由相对应的工厂实现。比较好理解:
public interface FoodFactory {
Food createFood();
}
//炒饭工厂
public class FriedRiceFactory implements FoodFactory {
@Override
public Food createFood() {
Food food = new FriedRice();
return food;
}
}
//面条工厂
public class NoodlesFactory implements FoodFactory {
@Override
public Food createFood() {
Food food = new Noodles();
return food;
}
}
测试类:
public class Main {
public static void main(String[] args) {
FriedRiceFactory friedRiceFactory = new FriedRiceFactory();
Food friedRice = friedRiceFactory.createFood();
System.out.println(friedRice.toString());
NoodlesFactory noodlesFactory = new NoodlesFactory();
Food noodles = noodlesFactory.createFood();
System.out.println(noodles.toString());
}
}
抽象工厂模式
考虑以下场景:有饭店A和饭店B,两家饭店都会制作炒饭和面条,但其成本 或者售价不同,那么抽象工厂便有其用武之地。
抽象出一个”饭店接口”
public interface AbstractRestaurant {
Food createRice();
Food createNoodles();
}
分别实现A饭店和B饭店
public class RestaurantA implements AbstractRestaurant {
@Override
public Food createRice() {
Food food = new FriedRice(20, 5, "FriedRiceA");
return food;
}
@Override
public Food createNoodles() {
Food food = new Noodles(30, 15, "NoodlesA");
return food;
}
}
public class RestaurantB implements AbstractRestaurant {
@Override
public Food createRice() {
Food food = new FriedRice(59, 14, "FriedRiceB");
return food;
}
@Override
public Food createNoodles() {
Food food = new Noodles(34, 21, "NoodlesB");
return food;
}
}
测试程序:
public class Main {
public static void main(String[] args) {
RestaurantA A = new RestaurantA();
RestaurantB B = new RestaurantB();
Food AFriedRice = A.createRice();
Food ANoodles = A.createNoodles();
System.out.println(AFriedRice);
System.out.println(ANoodles);
Food BFriedRice = B.createRice();
Food BNoodles = B.createNoodles();
System.out.println(BFriedRice);
System.out.println(BNoodles);
}
}
总结
很浅的个人理解,希望工作中能加深理解。。。