软件设计模式-适配器模式-外观模式

导语

适配器模式和外观模式他们很容易让人混淆他们真正的用法
适配器模式的使用场景是需要转换一个或多个接口到我们的目标类中
外观模式则是简化复杂接口的一个使用 其主要作用不是用来转换接口的 而是一个简化的主要作用

适配器模式

日常生活中我们为了让各种不同样式的插头都能和插座兼容 那么我们就需要适配器这个组件 同样 在设计模式中 我们也有适配器模式这样一种概念

适配器模式的最主要的作用就是对接口的一个转换

我们这里以火鸡 和 之前的鸭子为例 看看火鸡如何转换成一只鸭子 以及 鸭子如何转换成一只火鸡
这里鸭子转火鸡的时候 没有采用HeadFirst那本书上的策略 那个随机性不是很明确 所以加入一个控制变量 然后每五次飞行一次

/**  
* @Title: AdapterModelTest.java  
* @Package   
* @Description: TODO(用一句话描述该文件做什么)  
* @author Lustre  
* @date 2019年12月11日  
* @version V1.0  
*/
/**
* @author Nigel
* @version 创建文件时间:2019年12月11日 上午8:57:15
*/


/**
 * 
* @ClassName: Duck  
* @Description: 这里我们创建一个抽象鸭子基类 这里为了简单 就不在使用组合接口 
* @author Nigel  
* @date 2019年12月11日  
*
 */
abstract class Duck {
     
	public abstract void quark();
	public abstract void fly();
}

class MallardDuck extends Duck {
     

	@Override
	public void quark() {
     
		System.out.println("as a duck, i can quark!");
	}

	@Override
	public void fly() {
     
		System.out.println("as a duck i can fly a long distance!");
	}
}

/**
 * 
* @ClassName: Turkey  
* @Description: 这里同样定义了一个Turkey抽象基类
* @author Nigel  
* @date 2019年12月11日  
*
 */
abstract class Turkey {
     
	public abstract void rumble();
	public abstract void flyShort();
}

class BlackTurkey extends Turkey {
     

	@Override
	public void rumble() {
     
		// TODO Auto-generated method stub
		System.out.println("as a turkey, i can rumble!");
	}

	@Override
	public void flyShort() {
     
		// TODO Auto-generated method stub
		System.out.println("as a turkey, i can fly a short distance!");
	}
}

/*
 * 接下来创建两个适配器 分别用来供火鸡变鸭子 以及 鸭子假装成是一只火鸡~
 */
/**
 * 
* @ClassName: TurkeyAdapter  
* @Description: 作为一个适配器 显然是需要提供两个参数的 一个是被Adaptee 一个是Target 作为火鸡的适配器 我们最终可以转换成一只鸭子
* @author Nigel  
* @date 2019年12月11日  
*
 */
class TurkeyAdapter extends Duck {
     
	private Turkey turkey;
	/**  
	* 需要提供一只用来转换的火鸡 
	*    
	*/
	public TurkeyAdapter(Turkey turkey) {
     
		// TODO Auto-generated constructor stub
		this.turkey = turkey;
	}
	
	@Override
	public void quark() {
     
		// 这里我们将火鸡的叫声等同于一只鸭子
		turkey.rumble();
	}

	@Override
	public void fly() {
     
		// 由于火鸡飞行距离短 所以我们让他多飞几次 毕竟我们让它假装成"鸭子"
		for (int i = 0; i < 5; i++) {
     
			turkey.flyShort();
		}
	}
	
}

/**
 * 
* @ClassName: DuckAdapter  
* @Description: 现在 我们将一只鸭子转变成一只火鸡
* @author Nigel  
* @date 2019年12月11日  
*
 */
class DuckAdapter extends Turkey {
     
	private Duck duck;
	private Integer flyNum = 0;
	/**  
	* 创建一个新的实例 DuckAdapter.  
	*    
	*/
	public DuckAdapter(Duck duck) {
     
		this.duck = duck;
	}
	
	@Override
	public void rumble() {
     
		// TODO Auto-generated method stub
		duck.quark();
	}

	@Override
	public void flyShort() {
     
		// 由于鸭子飞行距离长 所以我们需要控制鸭子的飞行 即平均五次才飞行一次
		if (flyNum++ % 5 == 0 && flyNum != 0) {
     
			duck.fly();
		}
	}
	
}


/**  
* @ClassName: AdapterModelTest  
* @Description: TODO(这里用一句话描述这个类的作用)  
* @author Nigel  
* @date 2019年12月11日  
*    
*/
public class AdapterModelTest {
     

	/**  
	* @Title: main  
	* @Description: TODO  
	* @param args    
	* @return void    
	* @throws
	*/
	public static void main(String[] args) {
     
		// 现在测试适配器的是否好用
		//现在我们想将一只火鸡转换成一只鸭子
		System.out.println("测试火鸡转鸭子:");
		Duck fakeDuck = new TurkeyAdapter(new BlackTurkey());
		fakeDuck.quark();
		fakeDuck.fly();
		//现在我们想将一只鸭子转换成一只火鸡
		System.out.println("测试鸭子转火鸡:");
		Turkey fakeTurkey = new DuckAdapter(new MallardDuck());
		fakeTurkey.rumble();
		for (int i = 0; i < 5; i++) {
     
			fakeTurkey.flyShort();
		}
	}
}

外观模式(Facade Model)

外观模式能很好的体现 最少知识原则 即类只访问属于自己的或者自己创建的一些属于自己的类 而不是通过一个中介者间接调用另一个不属于自己管理的类的方法

如何遵循最小知识原则呢 在该对象的方法内 我们只应该调用属于以下范围的事物

  1. 访问方法所属对象本身
  2. 访问被当做参数传入的对象的方法
  3. 此方法创建或者实例化的对象
  4. 对象自己拥有的组件

外观模式的官方定义如下
外观模式提供了一个统一的接口 用来访问子系统的一群接口 外观定义了一个高层接口 从而能尽可能的保证最小知识原则

这里我们以家庭影院的例子 开启家庭影院 要很多操作 而用户的话应该只需要一键化傻瓜式操作就可以自动启动大量设备 而不是用户一个按钮一个指定操作 这样肯定会极大的降低用户的体验性

示例代码如下所示

/**  
* @Title: FacadeModelTest.java  
* @Package   
* @Description: TODO(用一句话描述该文件做什么)  
* @author Lustre  
* @date 2019年12月11日  
* @version V1.0  
*/
/**
* @author Nigel
* @version 创建文件时间:2019年12月11日 上午9:41:59
*/

/*
 * 声明一堆组件
 */

abstract class Component {
     
	public void on() {
     
		System.out.println(this.getClass().getName() + "is on!");
	}
	public void off() {
     
		System.out.println(this.getClass().getName() + "is off!");
	}
}

class Amplifier extends Component{
     }

class Tuner extends Component {
     }

class DvdPlayer extends Component {
     }

class CdPlayer extends Component {
     }

class Projector extends Component {
     }

class ThreaterLights extends Component {
     }

class Screen extends Component {
     }

class PopcornPopper extends Component {
     }
/**
 * 
* @ClassName: HomeTheaterFacade  
* @Description: 我们的外观模式 用来简化看电影的操作
* @author Nigel  
* @date 2019年12月11日  
*
 */
class HomeTheaterFacade {
     
	Amplifier amp;
	Tuner tuner;
	DvdPlayer dvdPlayer;
	CdPlayer cd;
	Projector projector;
	ThreaterLights threaterLights;
	Screen screen;
	PopcornPopper popper;
	public HomeTheaterFacade(Amplifier amp, Tuner tuner, DvdPlayer dvdPlayer, CdPlayer cd, Projector projector,
			ThreaterLights threaterLights, Screen screen, PopcornPopper popper) {
     
		super();
		this.amp = amp;
		this.tuner = tuner;
		this.dvdPlayer = dvdPlayer;
		this.cd = cd;
		this.projector = projector;
		this.threaterLights = threaterLights;
		this.screen = screen;
		this.popper = popper;
	}
	
	/**  
	* @Title: watchMovie  
	* @Description: TODO      
	* @return void    
	* @throws
	*/
	public void watchMovie() {
     
		// TODO Auto-generated method stub
		System.out.println("now watch a movie!");
		popper.on();
		threaterLights.on();
		amp.on();
		projector.on();
		screen.off();
		dvdPlayer.on();
	}
	
	public void endMovie() {
     
		//... 这里省略不写了
	}
}

/**  
* @ClassName: FacadeModelTest  
* @Description: TODO(这里用一句话描述这个类的作用)  
* @author Nigel  
* @date 2019年12月11日  
*    
*/
public class FacadeModelTest {
     

	/**  
	* @Title: main  
	* @Description: TODO  
	* @param args    
	* @return void    
	* @throws
	*/
	public static void main(String[] args) {
     
		// 此时将所有的处理权都交给homeThreater处理 而不用用户一个个去调用 这样一方面可以保证代码的复用 另一方面也可以保证最小知识原则
		Amplifier amp = new Amplifier();
		Tuner tuner = new Tuner();
		DvdPlayer dvdPlayer = new DvdPlayer();
		CdPlayer cd = new CdPlayer();
		Projector projector = new Projector();
		ThreaterLights threaterLights = new ThreaterLights();
		Screen screen = new Screen();
		PopcornPopper popper = new PopcornPopper();
		HomeTheaterFacade homeTheater = new HomeTheaterFacade(amp, tuner, dvdPlayer, cd, projector, threaterLights, screen, popper);
		homeTheater.watchMovie();
	}
}

你可能感兴趣的:(软件设计模式,软件设计模式,java)