package wrapperFacadePatte;
/**
 * 外观模式:
 * 百度百科:
 * ☆ 为子系统中的一组接口提供一个一致的界面,定义一个高层接口,这个接口使得这一子系统更加容易使用。
 * 适用场景:
 *  (1) 设计初期阶段,应该有意识的将不同层分离,层与层之间建立外观模式。
 *	(2) 开发阶段,子系统越来越复杂,增加外观模式提供一个简单的调用接口。
 *	(3) 维护一个大型遗留系统的时候,可能这个系统已经非常难以维护和扩展,但又包含非常重要的功能,为其开发一个外观类,以便新系统与其交互。
 * 
 * 优点:
 *  1)对客户屏蔽子系统组件,减少了客户处理的对象数目并使得子系统使用起来更加容易。 
 *    通过引入外观模式,客户代码将变得很简单,与之关联的对象也很少。
	2)实现了子系统与客户之间的松耦合关系,这使得子系统的组件变化不会影响到调用它的客户类,只需要调整外观类即可。
	3)降低了大型软件系统中的编译依赖性,并简化了系统在不同平台之间的移植过程,
	      因为编译一个子系统一般不需要编译所有其他的子系统。一个子系统的修改对其他子系统没有任何影响,
	      而且子系统内部变化也不会影响到外观对象。
	4)只是提供了一个访问子系统的统一入口,并不影响用户直接使用子系统类。
	
   	缺点:
   	1) 不能很好地限制客户使用子系统类,如果对客户访问子系统类做太多的限制则减少了可变性和灵活性。
	2) 在不引入抽象外观类的情况下,增加新的子系统可能需要修改外观类或客户端的源代码,违背了“开放封闭原则”。
	
	
	看不懂? 没关系 看代码就懂了!!
 * 
 *@author LiMing  E-mail:1151143484@qq.com
 *@date 2017年6月15日  上午8:14:06
 */
public class WrapperFacadePatte {
	public static void main(String[] args) {
		Facade facade = new Facade();
		//如果是一般的编写 这里需要new 三个对象 然后分别调用method方法  但是写了外观类之后 这里只需要调用外观类的方法就行了
		//在这里客户端是不允许直接使用Original1 Original2 Original3 的 所以这也是缺点 不灵活
		//而且增加、删除或更换与外观类交互的子系统类 必须修改外观类或客户端的源代码,这将违背开闭原则,  所以可以引入抽象外观类 对外观类进行升级
		facade.Method();
		
		//抽象外观类的正确打开方式  新增一个Original4 如果没有抽象外观的话 是需要修改Facade类的 但是现在不用  现在写一个NewFacade就行了	
		NewFacade facade2 = new NewFacade();
		facade2.Method();
		
		//其实最正确的打开方式是 通过xml 获取NewFacade 然后通过反射获取实例
		NewFacade facade3;
		try {
			facade3 = (NewFacade) Class.forName("wrapperFacadePatte.NewFacade").newInstance();
			facade3.Method();
		} catch (InstantiationException | IllegalAccessException
				| ClassNotFoundException e) {
			e.printStackTrace();
		}
		
		
	  /******,确保系统中有且仅有一个EncryptFacade类的实例,从而避免生成多个EncryptFacade对象,节约系统资源,提高程序性能。  单例模式********/
		SimpleNewFacade  facade4 = 	SimpleNewFacade.getInstance();
		facade4.Method();
		
	}
 
}

/*
 * 这是功能类1  2  3
 */
class Original1{
	public void Method(){
		System.out.println("Original1   11的method");
	}
}
class Original2{
	public void Method(){
		System.out.println("Original2   22的method");
	}
}
class Original3{
	public void Method(){
		System.out.println("Original3    33的method");
	}
}
/*
 * 新增的类
 */
class Original4{
	public void Method(){
		System.out.println("Original4    44的method");
	}
}

/*
 * 这就是外观类  这个类刚开始没有 实现AbstractFacade 因为刚开始没有抽象外观类  如果在项目中刚开始应该设计抽象外观类 第一个实现应该要继承AbstractFacade的
 */
class Facade{
	Original1 original1 = new Original1();
	Original2 original2 = new Original2();
	Original3 original3 = new Original3();
	public void Method(){
		original1.Method();
		original2.Method();
		original3.Method();
	}
}

/*******************************************抽象外观类*********************************/

/*
 * 抽象外观
 */
interface AbstractFacade{
	public abstract void Method();
}
class NewFacade{
	Original1 original1 = new Original1();
	Original2 original2 = new Original2();
	Original3 original3 = new Original3();
	//新增的4 以前是没有的
	Original4 original4 = new Original4();
	public void Method(){
		original1.Method();
		original2.Method();
		original3.Method();
		original4.Method();
	}
}

/*
 * 在xml中配置具体的外观类对应的真实类 比如说facade 对应的是NewFacade 在使用的时候直接获取NewFacade 然后通过反射进行初始化
 * 
 * 
<?xml version="1.0" encoding="utf-8" ?>  
<configuration>  
  <appSettings>  
    <add key="facade" value="wrapperFacadePatte.NewFacade"/>  
  </appSettings>  
</configuration>  */






/**********************************单例抽象外观类*****************************************/
class SimpleNewFacade{
	private static SimpleNewFacade instance = new SimpleNewFacade();  
	Original1 original1 ;
	Original2 original2;
	Original3 original3;
	Original4 original4;
	private SimpleNewFacade() {    
		 	 original1 = new Original1();
			 original2 = new Original2();
			 original3 = new Original3();  
			 original4 = new Original4();
	    }    
	public void Method(){
		original1.Method();
		original2.Method();
		original3.Method();
		original4.Method();
	}
	  public static SimpleNewFacade getInstance() {         
          return instance;       
 }    
}