什么是设计模式?什么是抽象工厂设计模式?
设计模式:在编写代码的过程中,根据不同的业务场景,封装出来的各种情况,整理出来的
抽象工厂设计模式:基于工厂模式,再次封装
说明:必须先学会工厂模式,才能更好理解抽象工厂
正常需求遇到了什么问题?使用什么设计模式能解决问题?
开发一个需要给猫、狗、老虎喂食,然后让它们出去玩,然后再进行打扫
分析:
1.需要给猫、狗、老虎喂食
2.需要让猫、狗、老虎出去玩
3.需要使用工具进行打扫
动物工厂
//动物
public interface Pet {
//吃
void eat();
//玩
void play();
}
public class Cat implements Pet{
@Override
public void eat() {
System.out.println("小猫开始吃");
}
@Override
public void play() {
System.out.println("小猫开始抓鱼");
}
}
public class Dog implements Pet{
@Override
public void eat() {
System.out.println("小狗开始吃");
}
@Override
public void play() {
System.out.println("小狗开始追球");
}
}
public class Tiger implements Pet{
@Override
public void eat() {
System.out.println("大老虎开始吃");
}
@Override
public void play() {
System.out.println("大老虎开始查看领地");
}
}
//动物工厂
public class PetFactory {
public static Pet createPet(String name) {
if("cat".equals(name)) {
return new Cat();
}else if ("dog".equals(name)) {
return new Dog();
}else if ("tiger".equals(name)) {
return new Tiger();
}
return null;
}
}
打扫工具工厂
//清理打扫工具
public interface CleaningTool {
//清理打扫
void clean();
}
public class Rag implements CleaningTool{
@Override
public void clean() {
System.out.println("开始用抹布清理");
}
}
public class VacuumCleaner implements CleaningTool {
@Override
public void clean() {
System.out.println("使用吸尘器打扫");
}
}
//清理工具封装
public class CleaningToolFactory {
//获得工具
public static CleaningTool create(String name) {
if("rag".equals(name)) {
return new Rag();
}else if("vacuumCleaner".equals(name)) {
return new VacuumCleaner();
}
return null;
}
}
测试:
public class FactoryPatternTest {
public static void main(String[] args) {
//周一
System.out.println("今天周一");
//给猫喂食,让猫出去玩
Pet cat = PetFactory.createPet("cat");
cat.eat();
cat.play();
//给猫喂食,让猫出去玩
Pet dog = PetFactory.createPet("dog");
dog.eat();
dog.play();
//给猫喂食,让猫出去玩
Pet tiger = PetFactory.createPet("tiger");
tiger.eat();
tiger.play();
//使用吸尘器打扫
CleaningTool vacuumCleaner = CleaningToolFactory.create("vacuumCleaner");
vacuumCleaner.clean();
//使用抹布清理
CleaningTool rag = CleaningToolFactory.create("rag");
rag.clean();
//周二。
System.out.println("今天周二");
//给猫喂食,让猫出去玩
Pet cat2 = PetFactory.createPet("cat");
cat2.eat();
cat2.play();
//使用抹布清理
CleaningTool rag2 = CleaningToolFactory.create("rag");
rag2.clean();
//....更多组合
}
}
今天周一
小猫开始吃
小猫开始抓鱼
小狗开始吃
小狗开始追球
大老虎开始吃
大老虎开始查看领地
使用吸尘器打扫
开始用抹布清理
今天周二
小猫开始吃
小猫开始抓鱼
开始用抹布清理
发现问题
1.当一个业务,需要使用很多类业务组合,需要知道很多的工厂类
2.当需要整合多种业务进行某一件事情时,组合的方式太多了,情况太多,会出现很多各种方法,比如:周一、周二等等组合
3.工厂类发生变化时,需要修改所有对工厂类引用的代码
怎么去解决
新增抽象整合类,然后根据整合类,新增抽象工厂
//整合抽象类,把动物、打扫2个接口整合起来,让原来的动物工厂、打扫工厂继承
public abstract class AbstractIntegration {
public Pet pet(String name) {
return null;
}
public CleaningTool clean(String name) {
return null;
}
}
//修改清洁工厂
public class CleaningToolFactory extends AbstractIntegration{
//获得工具
public static CleaningTool create(String name) {
if("rag".equals(name)) {
return new Rag();
}else if("vacuumCleaner".equals(name)) {
return new VacuumCleaner();
}
return null;
}
//重写抽象类方法
@Override
public CleaningTool clean(String name) {
return CleaningToolFactory.create(name);
}
}
//修改动物工厂
public class PetFactory extends AbstractIntegration {
public static Pet createPet(String name) {
if("cat".equals(name)) {
return new Cat();
}else if ("dog".equals(name)) {
return new Dog();
}else if ("tiger".equals(name)) {
return new Tiger();
}
return null;
}
//重写抽象类方法
@Override
public Pet pet(String name) {
return PetFactory.createPet(name);
}
}
//新建整合抽象类工厂(抽象工厂)
public class AbstractFactory {
//返回动物,打扫后的整合抽象类的子类
public static AbstractIntegration create(String name) {
if("pet".equals(name)) {
return new PetFactory();
}else if("cleaningTool".equals(name)) {
return new CleaningToolFactory();
}
return null;
}
}
测试:
public class FactoryPatternTest {
public static void main(String[] args) {
AbstractIntegration pet = AbstractFactory.create("pet");
//周一
System.out.println("今天周一");
//给猫喂食,让猫出去玩
Pet cat = pet.pet("cat");
cat.eat();
cat.play();
//给猫喂食,让猫出去玩
Pet dog = pet.pet("dog");
dog.eat();
dog.play();
//给猫喂食,让猫出去玩
Pet tiger = pet.pet("tiger");
tiger.eat();
tiger.play();
//使用吸尘器打扫
AbstractIntegration cleaningTool = AbstractFactory.create("cleaningTool");
CleaningTool vacuumCleaner = cleaningTool.clean("vacuumCleaner");
vacuumCleaner.clean();
//使用抹布清理
CleaningTool rag = cleaningTool.clean("rag");
rag.clean();
//周二。
System.out.println("今天周二");
AbstractIntegration pet2 = AbstractFactory.create("pet");
//给猫喂食,让猫出去玩
Pet cat2 = pet2.pet("cat");
cat2.eat();
cat2.play();
//使用抹布清理
AbstractIntegration cleaningTool2 = AbstractFactory.create("cleaningTool");
CleaningTool rag2 = cleaningTool2.clean("rag");
rag2.clean();
// //周一
// System.out.println("今天周一");
// //给猫喂食,让猫出去玩
// Pet cat = PetFactory.createPet("cat");
// cat.eat();
// cat.play();
// //给猫喂食,让猫出去玩
// Pet dog = PetFactory.createPet("dog");
// dog.eat();
// dog.play();
// //给猫喂食,让猫出去玩
// Pet tiger = PetFactory.createPet("tiger");
// tiger.eat();
// tiger.play();
//
// //使用吸尘器打扫
// CleaningTool vacuumCleaner = CleaningToolFactory.create("vacuumCleaner");
// vacuumCleaner.clean();
// //使用抹布清理
// CleaningTool rag = CleaningToolFactory.create("rag");
// rag.clean();
//
//
// //周二。
// System.out.println("今天周二");
// //给猫喂食,让猫出去玩
// Pet cat2 = PetFactory.createPet("cat");
// cat2.eat();
// cat2.play();
// //使用抹布清理
// CleaningTool rag2 = CleaningToolFactory.create("rag");
// rag2.clean();
//....更多组合
}
}
测试结果:
今天周一
小猫开始吃
小猫开始抓鱼
小狗开始吃
小狗开始追球
大老虎开始吃
大老虎开始查看领地
使用吸尘器打扫
开始用抹布清理
今天周二
小猫开始吃
小猫开始抓鱼
开始用抹布清理
问题 | 解决 | 解决方式 | 解决后新问题 |
当一个业务,需要使用很多类业务组合,需要知道很多的工厂类 | 是 | 业务中的所有工厂都整合成一个新的抽象类 | 需要给原来工厂命名name字符串 |
当需要整合多种业务进行某一件事情时,组合的方式太多了,情况太多,会出现很多各种方法,比如:周一、周二等等组合 | 否 | ||
工厂类发生变化时,需要修改所有对工厂类引用的代码 | 是 | 使用一个工厂,通过方法的方式获取不通封装后的工厂(解耦) | 如果一直用工厂模式,会一直累加工厂类,代码更复杂了 |
总结
1.在使用工厂模式的代码上,进行再一次封装,外部只需要了解抽象工厂,就可以获取抽象工厂封装的所有其他工厂。
2.在使用工厂模式的代码基础上,在进行了一次解耦
3.工厂模式和抽象工厂模式,都解决不了业务多种组合的问题
待研究:工厂模式、抽象工厂模式,是不是可以无限封装,就和写框架一样,最后封装到自己也看不懂,只能说牛批?