设计模式自学笔记003_Real(装饰器设计模式、适配器设计模式)
一、装饰器设计模式
在之前的代理设计模式中,我们回对类中的方法进行拓展,现在,吴国一个类需要添加新的功能,即需要添加新的方法实现新的功能,那么第一种方式就是另外创建一个类来继承这个类,然后重写这个类的方法,并添加需要添加的新方法来实现新的功能。那么第二种方式就是利用装饰器设计模式。
装饰器设计模式就是先建立一个公共的接口类,然后具体的类来实现这个接口类的方法,如果我们要在具体类中添加新的方法功能,则再建立一个装饰器类,创建原始类的实例化对象,并重写接口方法,利用实例化对象来调用原始类的方法,然后我们在装饰器类中添加新的方法来实现新的功能。
我们举一个机器人的例子,比如现在有一个公司生产了一个机器人,他能够唱歌和跳舞两种功能,但是现在接到新的需求,希望实现新的新的额功能,比如扫地和拖地,那么如果根据装饰器设计模式的原理,我们可以设计一种外接骨骼,外接骨骼上又手和脚,只要安装在原来的机器人身上就能实现扫地、拖地的功能,这样就不需要重新设计机器人了,而且原始的机器人还可以再用。例子的代码如下:
public class DecoratorDesign01 {
public static void main(String[] args) {
DecoratorRobot robot = new DecoratorRobot(new InitialRobot());
robot.dance();
robot.sing();
robot.Sweep();
robot.Mop();
}
}
//公共接口类
public interface Robot {
void sing();
void dance();
}
//初始的类
class InitialRobot implements Robot{
@Override
public void sing() {
System.out.println("机器人唱歌");
}
@Override
public void dance() {
System.out.println("机器人在跳舞");
}
}
//装饰器类
class DecoratorRobot implements Robot{
private InitialRobot robot;
public DecoratorRobot(InitialRobot robot) {
this.robot = robot;
}
@Override
public void sing() {
robot.sing();
}
@Override
public void dance() {
robot.dance();
}
//添加新的功能:扫地
public void Sweep(){
System.out.println("机器人在扫地");
}
//添加新的功能:拖地
public void Mop(){
System.out.println("机器人在拖地");
}
}
输出结果:
机器人在跳舞
机器人唱歌
机器人在扫地
机器人在拖地
二、适配器设计模式
将某个类的接口转换成客户端期望的另一个接口表示,主要目的是让原本接口不匹配的你能一起工作的两个类可以协同工作,别名是包装器设计模式。
主要分为三类:类适配器模式、对象适配器模式、接口适配器模式
目的就是让原本不兼容的类可以兼容使用。
1、类适配器:
那么我们利用适配器的例子来编写一段代码:加入现在饿哦腰围手机充电,但是家庭电源电压为220V,手机充电需要5V,这样我们需要一个适配器将电压从220V转换为5V进行充电。代码如下:
//被适配的类
public class Voltage220V {
//输出220伏的电压
public int output220V(){
int src = 220;
System.out.println("电压"+src+"伏");
return src;
}
}
//适配接口
public interface Voltage5V {
int output5V();
}
//适配器类
public class VoltageAdapter1 extends Voltage220V implements Voltage5V{
@Override
public int output5V() {
//获取220V电压
int srcV = output220V();
int dstV = srcV / 44;
return dstV;
}
}
public class Phone {
//充电的方法
public void charging(Voltage5V voltage5V){
if(voltage5V.output5V() == 5){
System.out.println("电压为5V,可以充电");
}else if(voltage5V.output5V() > 5){
System.out.println("电压过高,不能充电");
}
}
}
public class AdapterDesign001 {
public static void main(String[] args) {
System.out.println("=== 类适配器模式 ===");
Phone phone = new Phone();
phone.charging(new VoltageAdapter1());
}
}
2、对象适配器
类适配器设计模式解决了接口不兼容的问题,但是,一般来说我们在编程中能不使用继承就不要使用继承关系,二类适配器需要适配器类去继承被适配的类,所以为了解决这一问题,对象适配器出现,我们不需要去继承被适配类,直接在适配器类中创建被适配类的实例即可,如果将上面的例子进行改进,只需要改动适配器类即可,即去掉继承关系,在适配器类中创建Voltage220V类的实例化对象供适配器使用。代码如下:
//被适配的类
public class Voltage220V {
//输出220伏的电压
public int output220V(){
int src = 220;
System.out.println("电压"+src+"伏");
return src;
}
}
//适配接口
public interface Voltage5V {
int output5V();
}
//适配器类
public class VoltageAdapter1 implements Voltage5V{
private Voltage220V voltage220V = new Voltage220V();
public VoltageAdapter1(Voltage220V voltage220V) {
this.voltage220V = voltage220V;
}
@Override
public int output5V() {
//获取220V电压
int srcV = voltage220V.output220V();
int dstV = srcV / 44;
return dstV;
}
}
public class Phone {
//充电的方法
public void charging(Voltage5V voltage5V){
if(voltage5V.output5V() == 5){
System.out.println("电压为5V,可以充电");
}else if(voltage5V.output5V() > 5){
System.out.println("电压过高,不能充电");
}
}
}
public class AdapterDesign001 {
public static void main(String[] args) {
System.out.println("=== 对象适配器模式 ===");
Phone phone = new Phone();
phone.charging(new VoltageAdapter1(new Voltage220V()));
}
}
根据“合成复用原则”,在系统中尽量使用关联关系来代替继承关系。
对象适配器模式是适配器模式常用的一种。
3、接口适配器
接口适配器模式:举一个例子,现在有一个接口里面有很多的方法,fun1()、fun2()、fun3()、fun4()。比如说又四个方法,但是我们现在只需要用到其中的一个方法或两个方法,其他的方法不需要,但是一个类实现接口的话必须将接口中的方法全部实现,那么就会产生不必要的代码,那么接口适配器的解决方案就是新建一个抽象类,来实现接口的全部方法,但是都是空实现,只有方法,方法体时空的,然后当我们在使用的时候,直接新建抽象类,有选择的重写里面的方法即可。代码如下:
//接口类
public interface interface2 {
void fun1();
void fun2();
void fun3();
void fun4();
}
//将接口全部空实现的抽象类
public class abstractClass implements interface2{
@Override
public void fun1() {
}
@Override
public void fun2() {
}
@Override
public void fun3() {
}
@Override
public void fun4() {
}
}
public class Client2 {
public static void main(String[] args) {
abstractClass class1 = new abstractClass(){
@Override
public void fun2() {
System.out.println("调用了fun1()方法");
}
};
class1.fun2();
}
}