喵星之旅-沉睡的猫咪-工厂类型设计模式
一、简单工厂模式
创建一个工厂类,里面写方法负责创建对象。提供创建实例的功能,而无需关心具体实现。锅是由调用者和工厂一起负责的。
由于如果创建一个对象,不单是工厂类内部的问题,调用者往里面传入信息了,所以一旦出现问题是双方的问题。他解耦的结果是虽然锅没彻底甩出去,但是找了一个一起背锅的。
类关系图如下:
产品接口:
package create.simplefactory; public interface Food { public void cook(); }
具体产品1:
package create.simplefactory; public class Jiucaijidan implements Food { public void cook() { System.out.println("韭菜鸡蛋做好了"); } }
具体产品2:
package create.simplefactory; public class Xihongshijidan implements Food { public void cook() { System.out.println("西红柿鸡蛋做好了"); } }
工厂类:
package create.simplefactory; public class FoodFactory { public Food createByName(String name) { if ("Jiucaijidan".equals(name)) { return new Jiucaijidan(); } else if ("Xihongshijidan".equals(name)) { return new Xihongshijidan(); } return null; } public Food createByClassname(String name) { try { if (name != null && !"".equals(name)) { return (Food) Class.forName(name).newInstance(); } } catch (Exception e) { e.printStackTrace(); } return null; } public Food createByClass(Class<? extends Food> clazz) { try { if (clazz != null) { return clazz.newInstance(); } } catch (Exception e) { e.printStackTrace(); } return null; } }
测试类:
package create.simplefactory; public class Test { public static void main(String[] args) { Food f1 = new FoodFactory().createByName("Jiucaijidan"); f1.cook(); Food f2 = new FoodFactory().createByClassname("create.simplefactory.Xihongshijidan"); f2.cook(); Food f3 = new FoodFactory().createByClass(Xihongshijidan.class); f3.cook(); } }
二、工厂模式
对上面的进行包装,将类型相同、有关联的放在一起,上面创建接口,外界通过接口使用工厂。让工厂彻底成为背锅侠。这里使用工厂时,已经不需要调用者参与了,所以除了问题都是工厂相关的,完美甩锅。
关系图如下:
产品接口:
package create.factory; public interface Food { public void cook(); }
具体产品1:
package create.factory; public class Jiucaijidan implements Food { public void cook() { System.out.println("韭菜鸡蛋做好了"); } }
具体产品2:
package create.factory; public class Xihongshijidan implements Food { public void cook() { System.out.println("西红柿鸡蛋做好了"); } }
工厂接口:
package create.factory; public interface FoodFactory { public Food create(); }
具体工厂1:
package create.factory; public class JiucaiFactory implements FoodFactory { public Food create() { return new Jiucaijidan(); } }
具体工厂2:
package create.factory; public class XihongshiFactory implements FoodFactory { public Food create() { return new Xihongshijidan(); } }
测试类:
package create.factory; public class Test { public static void main(String[] args) { FoodFactory ff1 = new XihongshiFactory(); FoodFactory ff2 = new JiucaiFactory(); Food f1 = ff1.create(); Food f2 = ff2.create(); f1.cook(); f2.cook(); } }
三、抽象工厂模式
考虑工厂的出现,将里面的简单工厂用工厂替换,就是抽象工厂。而且可以出现多级抽象工厂。
如果工厂进行背锅,里面有一些质量好的工厂就会有意见,所以内部分裂了,内部进行甩锅,就是抽象工厂。工厂总接口越稳定、内部背锅规则越详细,那么甩锅的设计就更完善、这个抽象工厂越成功。
关系图如下(只是其中一种展现方式):
具体产品1:
package create.abstractfactory; public class XiangyouJiucaijidan implements Condiment,Food { @Override public void add() { System.out.println("添加香油的"); } @Override public void cook() { System.out.println("韭菜鸡蛋做好了"); } }
具体产品2:
package create.abstractfactory; public class XiangyouXihongshijidan implements Condiment, Food { @Override public void add() { System.out.println("添加香油的"); } @Override public void cook() { System.out.println("西红柿鸡蛋。"); } }
具体产品3:
package create.abstractfactory; public class JijingJiucaijidan implements Food, Condiment { public void cook() { System.out.println("韭菜鸡蛋做好了"); } @Override public void add() { System.out.println("添加鸡精。"); } }
具体产品4:
package create.abstractfactory; public class JijingXihongshijidan implements Food, Condiment { public void cook() { System.out.println("西红柿鸡蛋做好了"); } @Override public void add() { System.out.println("添加鸡精。"); } }
产品分类1:
package create.abstractfactory; public interface Condiment { void add(); }
产品分类2:
package create.abstractfactory; public interface Food { public void cook(); }
总产品接口:
package create.abstractfactory; public interface CookFactory { public Food createXihongshijidan() ; public Food createJiucaijidan() ; }
分类产品工厂1:
package create.abstractfactory; public class JijingFactory implements CookFactory { public Food createXihongshijidan() { return new JijingXihongshijidan(); } public Food createJiucaijidan() { return new JijingJiucaijidan(); } }
分类产品工厂2:
package create.abstractfactory; public class XiangyouFactory implements CookFactory { public Food createXihongshijidan() { return new XiangyouXihongshijidan(); } public Food createJiucaijidan() { return new XiangyouJiucaijidan(); } }
测试类:
package create.abstractfactory; public class Test { public static void main(String[] args) { CookFactory ff1 = new JijingFactory(); CookFactory ff2 = new XiangyouFactory(); Food f1 = ff1.createXihongshijidan(); Food f2 = ff2.createXihongshijidan(); f1.cook(); f2.cook(); } }
四、多级抽象工厂模式
考虑工厂模式,将简单工厂用抽象工厂替换。
如果工厂接口层级较高,需要考虑如果尽量少的改动上方接口进行接口分层,胡乱分层会出问题。层级越靠上的改动频率应该越低。
对于工厂之上的抽象系列,也可能是单纯的工厂里面进行产品分类形成的,可能是多个工厂合道一起也可能是一个工厂拆分。如果是拆分就看拆分的详细程度,决定了抽象程度。不管是合并还是拆分,其实都需要重构。想要一开始就设计完美是不可能的.
五、抽象工厂的实现步骤(以上面的抽象工厂为例)
1、分析具体的产品特性,找出2中不同类别的特征。
比如:香油的韭菜鸡蛋、鸡精的韭菜鸡蛋、香油的西红柿鸡蛋、鸡精的西红柿鸡蛋。
那么一个菜可以有主料和调两部分。
2、考虑2类特性那一个变化的几率比较低。
我个人认为调料新品种的出现会频率更高,那么就认为主料的变化相对固定。
3、根据变化频率低的创建总接口
接口:菜肴
里面两个方法:做一个西红柿鸡蛋
做一个韭菜鸡蛋
如果认为是调料稳定,那么这里应该是两外的两个方法:添加香油的食物、添加鸡精的食物。
4、根据总接口和具体菜肴,创建不同的工厂类
第一个工厂往里面添加香油
第二个工厂往里面添加鸡精
5、这时候考虑变化,我们认为调料是变化的,就会出现新的调料,比如生抽。
那么我们的变化是总接口不变化!!,然后添加一个新的工厂类。
如果总接口先变化,那么说明设计错误。
ps:项目地址 svn://47.105.188.20/kitty/2%E3%80%81code/pattern 用户名密码:reader/reader
作者:喵星兔
出处:https://www.cnblogs.com/kittybunny/
喵星之旅:https://www.cnblogs.com/kittybunny/p/12148641.html
我的视频:https://space.bilibili.com/518581788
更多内容:不咬人的小兔子
本博客所有文章仅用于学习、研究和交流目的,欢迎非商业性质转载。
我是兔子,我会喵,我叫喵星兔~~