设计模式之抽象工厂模式+原型模式+适配器模式+建造者模式结合使用与总结

在原抽象工厂模式+建造者模式中添加了原型模式和适配器模式

抽象工厂模式和建造者模式结合链接https://blog.csdn.net/qq_18625571/article/details/104416504

一、模式解析

1、原型模式

(1)概述

用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。在这里,原型实例指定了要创建的对象的种类。用这种方式创建对象非常高效,根本无须知道对象创建的细节。

(2)解决问题

主要解决对象的创建问题,提升创建对象的性能。每new一次就会调用一次构造函数,如果构造函数的执行时间很长,多次执行这个初始化操作就要消耗很多时间降低效率。一般在初始化的信息不发生变化的情况下,克隆是最高的方法,这即隐藏了对象创建的细节,又对性能是大大的提升。

(3)类图

在这里插入图片描述

(4)成员角色

Prototype(抽象原型类):声明克隆方法的接口,是所有具体原型类的公共父类,它可是抽象类也可以是接口,甚至可以是具体实现类。
ConcretePrototype(具体原型类):它实现抽象原型类中声明的克隆方法,在克隆方法中返回自己的一个克隆对象。
Client(客户端):在客户类中,让一个原型对象克隆自身从而创建一个新的对象。

(5)优缺点

优点

1.如果创建新的对象比较复杂时,可以利用原型模式简化对象的创建过程,同时也能够提高效率。
2.不用重新初始化对象,而是动态地获得对象运行时的状态。

缺点

1.在实现深克隆的时候可能需要比较复杂的代码。
2.需要为每一个类配备一个克隆方法,而且这个克隆方法需要对类的功能进行通盘考虑,这对全新的类来说不是很难,但对已有的类进行改造时,不一定是件容易的事,必须修改其源代码,违背了“开闭原则”。

(6)使用场景

1.对象种类繁多,无法将他们整合到一个类的时候; 难以根据类生成实例时; 想解耦框架与生成的实例时。
2.如果想要让生成实例的框架不再依赖于具体的类,这时,不能指定类名来生成实例,而要事先“注册”一个“原型”实例,然后通过复制该实例来生成新的实例。

2、适配器模式

详细链接:https://blog.csdn.net/zxt0601/article/details/52848004?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

(1)概述

将一个接口转换成客户希望的另一个接口,使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。适配器模式既可以作为类结构型模式,也可以作为对象结构型模式。

(2)解决问题

主要作用是在新接口和老接口之间进行适配,将原本不兼容的接口融合在一起工作。

(3)类图

在这里插入图片描述

(4)成员角色

Target(目标抽象类):目标抽象类定义客户所需接口,可以是一个抽象类或接口,也可以是具体类。
Adapter(适配器类):适配器可以调用另一个接口,作为一个转换器,对Adaptee和Target进行适配,适配器类是适配器模式的核心,在对象适配器中,它通过继承Target并关联一个Adaptee对象使二者产生联系。
Adaptee(适配者类):适配者即被适配的角色,它定义了一个已经存在的接口,这个接口需要适配,适配者类一般是一个具体类,包含了客户希望使用的业务方法,在某些情况下可能没有适配者类的源代码。

(5)优点

1.将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,无须修改原有结构。
2.增加了类的透明性和复用性,将具体的业务实现过程封装在适配者类中,对于客户端类而言是透明的,而且提高了适配者的复用性,同一个适配者类可以在多个不同的系统中复用。
3.灵活性和扩展性都非常好,通过使用配置文件,可以很方便地更换适配器,也可以在不修改原有代码的基础上增加新的适配器类,完全符合“开闭原则”。

(6)使用场景

1.系统需要使用一些现有的类,而这些类的接口(如方法名)不符合系统的需要,甚至没有这些类的源代码。
2.想创建一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。

源码分析适配器模式的典型应用

二、结合实例

还是以卖奶茶为例

1、抽象工厂模式

(1)首先创建抽象工厂,实现Cloneable接口(衔接后面的原型模式)。也就是原材料总工厂,相当于一个大型批发市场,所有的实体工厂都开在这里。

public abstract class Factory implements Cloneable{
	
	private String id;
    protected Factory factory;
	
    public abstract Milk CreateMilk();

    public abstract Tea CreateTea();
 
    public String getId() {
        return id;
    }
    
    public void setId(String id) {
        this.id = id;
    }
 
    public Object clone(){
        Object clone = null;
        try{
            clone = super.clone();
        }catch (CloneNotSupportedException e){
            e.printStackTrace();
        }
        return clone;
    }
}

(2)原材料工厂中涉及很多原材料产品种类,现在创建这些产品种类,即创建抽象产品

public interface Milk {
	public  String getMilk();
}

public interface Tea {
	public  String getTea();
}

(3)接着创建所需的具体产品。

public class PureMilk implements Milk {
	PureMilk(){
		System.out.print("加纯牛奶");
	}
    	@Override
	public String getMilk() {
		String string="在搅拌机里加纯牛奶";
		return string;
	}
}

public class Yogurt implements Milk {
	public Yogurt(){
		System.out.print("加酸奶");
	}
    	@Override
	public String getMilk() {
		String string="在搅拌机里加酸奶";
		return string;
	}
}

public class GreenTea implements Tea {
	public GreenTea(){
    	System.out.print("加绿茶");
	}
    	@Override
	public String getTea() {
		String string="在烤茶机里加绿茶";
		return string;
	}
}

public class RedTea implements Tea {
	public RedTea()	{
		System.out.print("加红茶");
	}
    	@Override
	public String getTea() {
		String string="在烤茶机里加红茶";
		return string;
	}
}

(4)具体原材料准备好了,则分到具体的工厂制作,所有的工厂都实现了clone()方法,可以理解为采购员去批发市场把需要的原料采购出来。

public class AFactory extends Factory {
//A厂
    public Milk CreateMilk(){
    	Milk milk = new PureMilk();
    	System.out.println("(产地:A厂)");
        return milk;
    }

    public Tea CreateTea(){
    	Tea tea = new GreenTea();
    	System.out.println("(产地:A厂)");
        return tea;
    }
}

public class BFactory extends Factory {
//B厂
    public Milk CreateMilk(){
    	Milk milk = new Yogurt();
    	System.out.println("(产地:B厂)");
        return milk;
    }

    public Tea CreateTea(){
    	Tea tea = new RedTea();
    	System.out.println("(产地:B厂)");
        return tea;
    }
}

2、原型模式

(5)创建一个类,从库中获取实体类,并把它们存储在一个 Hashtable 中。可以看做把从AB工厂批发过来的原料放在仓库里,等需要用的时候再取,就不需要每次用到原料都跑去市场购买。

public class FactoryCache {
	private static Hashtable<String,Factory> shapeMap = new Hashtable<String,Factory>();
	 
    public static Factory getFactory(String factoryId){
    	Factory cachedFactory = shapeMap.get(factoryId);
        return (Factory)cachedFactory.clone();
    }
 
    public static void loadCache(){
    	AFactory Afactory = new AFactory();
    	Afactory.setId("1");
        shapeMap.put(Afactory.getId(),Afactory);
 
        BFactory Bfactory = new BFactory();
        Bfactory.setId("2");
        shapeMap.put(Bfactory.getId(),Bfactory);
    }
}

(6)有了原材料工厂,可以着手制作奶茶了。店长(奶茶建造者Builder)(衔接后面的建造者模式)为抽象类,可以理解为店长为做奶茶了制作了一个“食谱”(里面包含制作需要的原料及方法)以及店长规定仓库里原料的存放位置,后厨打开门根据原料的存放位置取原料,其余事情店长不需要做。

public abstract class MilkTeaBuilder {
	
	public String name;
	
	public Milk milk;
	
	public Tea tea;
	
	public Factory cloneFactory;
		
	public abstract void buildMilk();
	
	public abstract void buildTea();
	
	public abstract void create();
	
	/**
	 * 打开仓库的门,按照工厂的序号取原料
	 */
	public Factory openDoor(int factorId) {
		FactoryCache.loadCache();
		if(factorId==1) {
			cloneFactory=(Factory) FactoryCache.getFactory("1");
		}
		else {
			cloneFactory=(Factory) FactoryCache.getFactory("2");
		}
		return cloneFactory;
	}
	
}

3、建造者模式

(7)在没有用适配器模式之前需要用到加工奶类和加工茶类两个机器。MilkMachine相当于Adaptee即原有的旧机器(衔接适配器模式)。

public class MilkMachine {
	public static void makingMilk(Milk milk) {
		String makeString=milk.getMilk();
		System.out.println(makeString);
	}
}

public class TeaMachine {
	public static void makingTea(Tea tea) {
		String makeString=tea.getTea();
		System.out.println(makeString);
	}
}

(8)由后厨们(具体建造者ConcreteBuilder)按照建造者Builder的“食谱”去仓库取原料再用机器制作具体的奶茶。

public class GreenMilkConBuilder extends MilkTeaBuilder{
	@Override
	public void buildMilk() {
		openDoor(1);
		milk=cloneFactory.CreateMilk();
		System.out.println("Factory: " + cloneFactory);
	}
	@Override
	public void buildTea() {
		openDoor(1);
		tea=cloneFactory.CreateTea();
		System.out.println("Factory: " + cloneFactory);
	}
	@Override
	public void create() {
		System.out.println("正在准备牛奶绿茶中......");	
        MilkMachine.makingMilk(milk);
		TeaMachine.makingTea(tea);
	}
}

public class GreenYogurtConBuilder extends MilkTeaBuilder{
	@Override
	public void buildMilk() {
		openDoor(2);
		milk=cloneFactory.CreateMilk();
		System.out.println("Factory: " + cloneFactory);
	}
	@Override
		openDoor(1);
		tea=cloneFactory.CreateTea();
		System.out.println("Factory: " + cloneFactory);
	}
	@Override
	public void create() {
		System.out.println("正在开始准备酸奶绿茶中......");
        MilkMachine.makingMilk(milk);
		TeaMachine.makingTea(tea);
	}
}

public class RedMilkConBuilder extends MilkTeaBuilder{
	@Override
	public void buildMilk() {
		openDoor(1);
		milk=cloneFactory.CreateMilk();
		System.out.println("Factory: " + cloneFactory);
	}
	@Override
	public void buildTea() {
		openDoor(2);
		tea=cloneFactory.CreateTea();
		System.out.println("Factory: " + cloneFactory);
	}
	@Override
	public void create() {	
		System.out.println("正在准备牛奶红茶中......");
        MilkMachine.makingMilk(milk);
		TeaMachine.makingTea(tea);
	}
}

public class RedYogurtConBuilder extends MilkTeaBuilder{
	@Override
	public void buildMilk() {
		openDoor(2);
		milk=cloneFactory.CreateMilk();
		System.out.println("Factory: " + cloneFactory);
	}
	@Override
	public void buildTea() {
		openDoor(2);
		tea=cloneFactory.CreateTea();
	}
	@Override
	public void create() {
		System.out.println("正在开始准备酸奶红茶中......");	
		MilkMachine.makingMilk(milk);
		TeaMachine.makingTea(tea);
	}
}

4、适配器模式

(9)由于用两个机器制造奶茶太繁琐,但是又不能在现有的机器里同时混合两种原料制作,所以老板打算更新设备,买了一个新升级加工牛奶的机器(可以同时加工茶类)newMachineTarget(接口)。

MilkMachine相当于Adaptee即原有的旧机器。

public interface newMachineTarget {

		public void newmaking(Milk milk,Tea tea);
}

(10)新机器的实体Adapter有以前旧机器MilkMachine的功能,还添加了TeaMachine的功能。

public class Adapter extends MilkMachine implements newMachineTarget {

	public void newmaking(Milk milk,Tea tea) {
		makingMilk(milk);
		
		//新加的烤茶功能
		String makeString=tea.getTea();
		System.out.println(makeString);
	}
}

(11)继续建造者模式后厨们(具体建造者ConcreteBuilder)使用新机器制作奶茶,将上述第(9)改成此步骤,修改 create()方法:

		MilkMachine.makingMilk(milk);
		TeaMachine.makingTea(tea);

改成

		newMachineTarget machine=new Adapter();
		machine.newmaking(milk,tea);//用新机器加工

其余GreenYogurtConBuilder、RedMilkConBuilder、RedYogurtConBuilder改法相同,如下

public class GreenMilkConBuilder extends MilkTeaBuilder{
	@Override
	public void buildMilk() {
		openDoor(1);
		milk=cloneFactory.CreateMilk();
		System.out.println("Factory: " + cloneFactory);
	}
	@Override
	public void buildTea() {
		openDoor(1);
		tea=cloneFactory.CreateTea();
		System.out.println("Factory: " + cloneFactory);
	}
	@Override
	public void create() {
		System.out.println("正在准备牛奶绿茶中......");		
		newMachineTarget machine=new Adapter();
		machine.newmaking(milk,tea);//用新机器加工
	}
}

(12)奶茶一切准备就绪,可以开店了。店里有服务员(指挥者类Director)一方面它隔离了客户与生产过程,即客户只看到菜单只能选择商品不能看到生产过程;另一方面它负责控制产品的生成过程。指挥者针对抽象建造者编程,客户端只需要知道具体建造者的类型,即可通过指挥者类调用建造者的相关方法,返回一个完整的产品对象,简单来说服务员Director和店长Builder说顾客Client要红茶,然后店长Builder安排具体后厨ConcreteBuilder生产相应产品。

public class MilkTeashop {
  
	public void menu() {
		System.out.println("************MENU************");
		System.out.println("1.RedMilk               2.GreenMilk");
		System.out.println("3.RedYogurt           4.GreenYogurt");
		System.out.println("*************END*************");
	}
	
	public void making(MilkTeaBuilder milkTea) {
		milkTea.buildMilk();
		milkTea.buildTea();
		milkTea.create();

	}
	
	public MilkTeaBuilder selectMilkTea() {
		MilkTeaBuilder milkTea=null;	
		Scanner s =new Scanner(System.in);
		System.out.print("请选择你的饮料");
		int num=s.nextInt();
		switch (num) {
		case 1:
			milkTea=new RedMilkConBuilder();
			break;
		case 2:
			milkTea=new GreenMilkConBuilder();
			break;
		case 3:
			milkTea=new RedYogurtConBuilder();
			break;
		case 4:
			milkTea=new GreenYogurtConBuilder();
			break;
		default:
			System.out.println("输入错误!");
			break;
		}
		making(milkTea);
		return milkTea;
	}
}

(13)测试奶茶店的运行情况

public class DrinkClient {

	public static void main(String[] args) {
		MilkTeashop coco = new MilkTeashop();
		coco.menu();
		coco.selectMilkTea();
	}
}

结果

在这里插入图片描述

发布了16 篇原创文章 · 获赞 5 · 访问量 720

猜你喜欢

转载自blog.csdn.net/qq_18625571/article/details/104552071
今日推荐