一、适配器模式
目的:将某个类的接口转换成某个期望接口的的标识,主要是为了兼容性的目的,属于结构性模式。适配器让原本接口不兼容的类 可以合作无间。
1. 类的适配器
现在有一个接口和一个类
public interface Voltage5V {
public int getVoltageBy5();
}
public class Voltage220V {
public int getVoltageBy220(){
return 220;
}
}
适配类将两个进行适配
// 适配类 需要对适配的两种东西进行继承或者实现
public class AdapterPattern extends Voltage220V implements Voltage5V{
@Override
public int getVoltageBy5() {
int src = this.getVoltageBy220(); // 实现接口的方法,并调用继承类的方式
int dest = src - 110; // 进行某种操作转换
return dest;
}
}
写一个调用的方法,表面上这个类是需要Voltage5V,我们可以将适配器传进去。
public class Phone {
public void charging(Voltage5V voltage){
System.out.println(voltage.getVoltageBy5());
}
}
// 主函数进行调用
Phone phone = new Phone();
phone.charging(new AdapterPattern()); // 把适配器传进去 相当于插在了转换口上
2. 对象适配器
在类的适配上修改了耦合高的特点,将继承转变成了组合的形式。
public class IphoneAdapter implements Voltage5V{
private Voltage220V voltage; // 转变成组合的模式
public IphoneAdapter(Voltage220V voltage){
this.voltage = voltage;
}
@Override
public int getVoltageBy5() {
int src = voltage.getVoltageBy220();
int dest = src - 110;
return dest;
}
}
main函数进行调用
Phone phone = new Phone();
phone.charging(new IphoneAdapter(new Voltage220V())); // 要适配 这样更灵活
3. 接口适配器
不想将所有的方法进行重写,只重写自己需要的方法。
用一个抽象类去实现接口中的所有方法,再用目标类进行继承抽象类,重写自己关心的方法。
public interface SrcInterface {
public void func1();
public void func2();
public void func3();
public void func4();
}
public abstract class DestClass implements SrcInterface{
public void func1() {}
public void func2() {}
public void func3() {}
public void func4() {}
}
// 主函数调用
DestClass destClass = new DestClass() { // 可以有选择的覆盖父类的子类
@Override
public void func1() {
System.out.println("----");
}
};
destClass.func1();
TIPS:适配器模式应用的时候一般通过 循环判断 instanceof 是否属于当前适配类的情况。
二、桥接模式
桥接模式实现了 实现部分和抽象放在两个不同类的层次中,使两个层次可以独立转变,属于结构型设计模式,基于类的最小设计原则,其目的是减少子类的个数(针对类爆炸的问题),替代多层继承的方案。主要解决是一对一的模式。
比如点茶水情况,有茶的种类和是否加料的两个维度。便可以将这两个维度独立开来。
加料的维度:需要一个接口,和具体实现
public interface Material {
public void addSth(String teaType);
}
public class Sugar implements Material{
@Override
public void addSth(String teaType) {
System.out.println(teaType + "添加了糖");
}
}
public class Milk implements Material{
@Override
public void addSth(String teaType) {
System.out.println(teaType + "添加了牛奶");
}
}
茶的种类维度,和加料的接口是组合的方式,具体的茶种类的实现都需要继承ITea即可。
public abstract class ITea {
private Material material;
public ITea(Material material){
this.material = material;
}
public abstract void orderTea(int count);
public void addSth(String teaType){
this.material.addSth(teaType);
}
}
public class Tea extends ITea{
public Tea(Material material) {
super(material);
}
@Override
public void orderTea(int count) {
System.out.println("点了"+count+"杯茶水");
}
@Override
public void addSth(String teaType) {
super.addSth(teaType + "普通茶");
}
}
三、装饰者模式
装饰者模式主要目的是 动态的将新功能附加到对象上,在对象功能扩展方面,比继承更有弹性。相比桥接模式可以是一对多模式。
首先这个抽象类有一个基本方法,凡是继承了食物这个接口的所有类都必须重写这个接口。
// 抽象的基类
public abstract class Food {
public String name;
public int price;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public abstract int calCost(); // 抽象方法供子类实现
}
具体的食物就继承这个类。
public class Jianbing extends Food{
public Jianbing(){
setName("煎饼果子");
setPrice(4);
}
@Override
public int calCost() {
return super.getPrice();
}
}
public class ShaoBing extends Food{
public ShaoBing(){
setName("泰山烧饼");
setPrice(1);
}
@Override
public int calCost() {
return super.getPrice();
}
}
装饰对象抽象相当于做一个通用的包装接口,后续的包装类只需要继承这个抽象类,然后再在其中加入新的行为或属性即可,而不需要重复封装。装饰类既继承又组合,这是装饰者模式的标志。
public abstract class FoodDecorator extends Food{
Food food;
public FoodDecorator(Food food){
this.food = food;
}
}
装饰者实现
public class Egg extends FoodDecorator{
public Egg(Food food) {
super(food);
setName("蛋蛋");
setPrice(2);
}
@Override
public int calCost() {
return food.calCost() + super.getPrice(); // food.calCost 是递归
}
}
public class Suggest extends FoodDecorator{
public Suggest(Food food) {
super(food);
setName("烤肠");
setPrice(3);
}
@Override
public int calCost() {
return food.calCost() + super.getPrice(); // food.calCost 是递归
}
}
主函数调用
Food jianbing = new Jianbing();
System.out.println(jianbing.price);
Food egg = new Egg(jianbing);
System.out.println(egg.calCost());
Suggest suggest = new Suggest(egg);
System.out.println(suggest.calCost());