1.装饰者模式
装饰(Decorator)模式中的角色:
-
抽象构件(Component)角色 :定义一个抽象接口以规范准备接收附加责任的对象。
-
具体构件(Concrete Component)角色 :实现抽象构件,通过装饰角色为其添加一些职责。
-
抽象装饰(Decorator)角色 : 继承或实现抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。
-
具体装饰(ConcreteDecorator)角色 :实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。
抽象构件:
//快餐:抽象构件
public abstract class FastFood {
private float price;//价格
private String desc; //描述
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public FastFood(float price, String desc) {
this.price = price;
this.desc = desc;
}
public FastFood() {
}
public abstract float cost();//算钱
}
具体构件:
//炒面:具体的构件角色
public class FriedNoodles extends FastFood {
public FriedNoodles() {
super(12,"炒面");
}
public float cost() {
return getPrice();
}
}
//炒饭:具体构件角色
public class FriedRice extends FastFood {
public FriedRice() {
super(10,"炒饭");
}
public float cost() {
return getPrice();
}
}
抽象装饰:
//抽象装饰角色
public abstract class Garnish extends FastFood {
//声明快餐类的变量
private FastFood fastFood;
//有参构造方法
public Garnish(FastFood fastFood, float price, String desc) {
super(price, desc);
this.fastFood = fastFood;
}
public FastFood getFastFood() {
return fastFood;
}
public void setFastFood(FastFood fastFood) {
this.fastFood = fastFood;
}
}
具体装饰:
//鸡蛋类:具体的装饰者角色
public class Egg extends Garnish {
public Egg(FastFood fastFood) {
super(fastFood,1,"鸡蛋");
}
public float cost() {
//计算价格
return getPrice() + getFastFood().cost();
}
@Override
public String getDesc() {
return super.getDesc() + getFastFood().getDesc();
}
}
//培根类:具体的装饰者角色
public class Bacon extends Garnish {
public Bacon(FastFood fastFood) {
super(fastFood,2,"培根");
}
public float cost() {
//计算价格
return getPrice() + getFastFood().cost();
}
@Override
public String getDesc() {
return super.getDesc() + getFastFood().getDesc();
}
}
测试类:
//测试类
public class Client {
public static void main(String[] args) {
//点一份炒饭
FastFood food = new FriedRice();
System.out.println(food.getDesc() + " " + food.cost() + "元");//炒饭 10.0元
System.out.println("===============");
//在上面的炒饭中加一个鸡蛋
food = new Egg(food);
System.out.println(food.getDesc() + " " + food.cost() + "元");//鸡蛋炒饭 11.0元
System.out.println("================");
//再加一个鸡蛋
food = new Egg(food);
System.out.println(food.getDesc() + " " + food.cost() + "元");//鸡蛋鸡蛋炒饭 12.0元
System.out.println("================");
food = new Bacon(food);
System.out.println(food.getDesc() + " " + food.cost() + "元");//培根鸡蛋鸡蛋炒饭 14.0元
}
}
2.桥接模式
桥接(Bridge)模式包含以下主要角色:
-
抽象化(Abstraction)角色 :定义抽象类,并包含一个对实现化对象的引用。
-
扩展抽象化(Refined Abstraction)角色 :是抽象化角色的子类,实现父类中的业务方法,并通过组合关系调用实现化角色中的业务方法。
-
实现化(Implementor)角色 :定义实现化角色的接口,供扩展抽象化角色调用。
-
具体实现化(Concrete Implementor)角色 :给出实现化角色接口的具体实现。
抽象化角色:
//操作系统版本:抽象化角色
public abstract class OperatingSystemVersion {
protected VideoFile videoFile;
public OperatingSystemVersion(VideoFile videoFile) {
this.videoFile = videoFile;
}
public abstract void play(String fileName);
}
扩展抽象化角色:
//Windows版本:扩展抽象化角色
public class Windows extends OperatingSystemVersion {
public Windows(VideoFile videoFile) {
super(videoFile);
}
public void play(String fileName) {
videoFile.decode(fileName);
}
}
//mac版本:扩展抽象化角色
public class Mac extends OperatingSystemVersion {
public Mac(VideoFile videoFile) {
super(videoFile);
}
public void play(String fileName) {
videoFile.decode(fileName);
}
}
实现化角色:
//视频文件:实现化
public interface VideoFile {
void decode(String fileName);
}
具体实现化角色:
//avi文件:具体实现化
public class AVIFile implements VideoFile {
public void decode(String fileName) {
System.out.println("avi视频文件:"+ fileName);
}
}
//rmvb文件:具体实现化
public class REVBBFile implements VideoFile {
public void decode(String fileName) {
System.out.println("rmvb文件:" + fileName);
}
}
测试类:
//测试类
public class Client {
public static void main(String[] args) {
OperatingSystemVersion os = new Windows(new AVIFile());
os.play("战狼3");
}
}
使用场景
-
当一个类存在两个独立变化的维度,且这两个维度都需要进行扩展时。
-
当一个系统不希望使用继承或因为多层次继承导致系统类的个数急剧增加时。
-
当一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性时。避免在两个层次之间建立静态的继承联系,通过桥接模式可以使它们在抽象层建立一个关联关系。
3.外观模式
外观(Facade)模式包含以下主要角色:
-
外观(Facade)角色:为多个子系统对外提供一个共同的接口。
-
子系统(Sub System)角色:实现系统的部分功能,客户可以通过外观角色访问它。
子系统角色:
//灯类:子系统角色
public class Light {
public void on() {
System.out.println("打开了灯....");
}
public void off() {
System.out.println("关闭了灯....");
}
}
//空调类:子系统角色
public class AirCondition {
public void on() {
System.out.println("打开了空调....");
}
public void off() {
System.out.println("关闭了空调....");
}
}
//电视类:子系统角色
public class TV {
public void on() {
System.out.println("打开了电视....");
}
public void off() {
System.out.println("关闭了电视....");
}
}
外观角色:
//智能音箱:外观角色
public class SmartAppliancesFacade {
private Light light;
private TV tv;
private AirCondition airCondition;
public SmartAppliancesFacade() {
light = new Light();
tv = new TV();
airCondition = new AirCondition();
}
public void say(String message) {
if(message.contains("打开")) {
on();
} else if(message.contains("关闭")) {
off();
} else {
System.out.println("我还听不懂你说的!!!");
}
}
//起床后一键开电器
private void on() {
System.out.println("起床了");
light.on();
tv.on();
airCondition.on();
}
//睡觉一键关电器
private void off() {
System.out.println("睡觉了");
light.off();
tv.off();
airCondition.off();
}
}
测试类:
//测试类
public class Client {
public static void main(String[] args) {
//创建外观对象
SmartAppliancesFacade facade = new SmartAppliancesFacade();
//客户端直接与外观对象进行交互
facade.say("打开家电");
facade.say("关闭家电");
}
}
好处:
-
降低了子系统与客户端之间的耦合度,使得子系统的变化不会影响调用它的客户类。
-
对客户屏蔽了子系统组件,减少了客户处理的对象数目,并使得子系统使用起来更加容易。
缺点:
-
不符合开闭原则,修改很麻烦
使用场景
-
对分层结构系统构建时,使用外观模式定义子系统中每层的入口点可以简化子系统之间的依赖关系。
-
当一个复杂系统的子系统很多时,外观模式可以为系统设计一个简单的接口供外界访问。
-
当客户端与多个子系统之间存在很大的联系时,引入外观模式可将它们分离,从而提高子系统的独立性和可移植性。