java设计模式之 装饰器模式
Posted 适AT
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java设计模式之 装饰器模式相关的知识,希望对你有一定的参考价值。
装饰器模式
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。
这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,动态给一个对象添提供了额外的功能。
我们通过下面的实例来演示装饰器模式的用法。模拟一个人从想吃饭、找饭店、享受美食、结束吃饭的过程
代码展示:
首先创建一个被修饰的接口 Eat
package decorator; //吃饭接口 public interface Eat { //吃饭方法 void eat(); }
创建一个被修饰者并且有自己的状态
package decorator; public class Person implements Eat { @Override public void eat() { System.out.println("======我饿了======"); } }
创建一个修饰者的抽象类
package decorator; public abstract class LikeEat implements Eat { private Eat eat; public LikeEat(Eat eat) { this.eat=eat; } @Override public void eat() { eat.eat(); } }
创建五个修饰类的扩展类(即--扩展修饰),分别拥有自己特定的状态,丰富被修饰的类
public class FindInMap extends LikeEat { public FindInMap(Eat eat) { super(eat); } public void userMap(){ System.out.println("打开地图寻找美食"); } @Override public void eat() { super.eat(); userMap(); } } public class GotoRestaurant extends LikeEat { public GotoRestaurant(Eat eat) { super(eat); } public void onWay(){ System.out.println("去往饭店的路上"); } @Override public void eat() { super.eat(); onWay(); } } public class InRestaurant extends LikeEat { public InRestaurant(Eat eat) { super(eat); } public void selectFoot(){ System.out.println("到达饭店选择食物"); } @Override public void eat() { super.eat(); selectFoot(); } } public class EatFoot extends LikeEat { public EatFoot(Eat eat) { super(eat); } public void eating(){ System.out.println("享用美食中"); } @Override public void eat() { super.eat(); eating(); } } public class endEat extends LikeEat { public endEat(Eat eat) { super(eat); } public void afterEat(){ System.out.println("=====美食结束====="); } @Override public void eat() { super.eat(); afterEat(); } }
创建测试类,测试修饰效果
public class EatTest { public static void main(String[] args) { Eat person = new Person(); likeEat likeEat = new endEat( new EatFoot( new InRestaurant( new GotoRestaurant( new FindInMap(person))))) ; likeEat.eat(); } }
运行结果:
总结:
A、LikeEat抽象类中,持有Eat接口,方法全部委托给该接口调用,目的是交给该接口的实现类即子类进行调用。
B、LikeEat抽象类的子类(具体装饰者),里面都有一个构造方法调用super(eat),这一句就体现了抽象类依赖于子类实现即抽象依赖于实现的原则。因为构造里面参数都是Eat接口,只要是该Eat的实现类都可以传递进去,即表现出
likeEat likeEat = new endEat(
new EatFoot(
new InRestaurant(
new GotoRestaurant(
new FindInMap(person)))))
这种结构的样子。所以当调用likeEat.eat()的时候,又因为每个具体装饰者类中,都先调用super.eat();方法,而该super已经由构造传递并指向了具体的某一个装饰者类(这个可以根据需要调换顺序),那么调用的即为装饰类的方法,然后才调用自身的装饰方法,即表现出一种装饰、链式的类似于过滤的行为。
C、具体被装饰者,可以定义初始的状态或者初始的自己的装饰,后面的装饰行为都在此基础上一步一步进行点缀、装饰。
D、装饰者模式的设计原则为:
对扩展开放、对修改关闭,这句话体现在我如果想扩展被装饰者类的行为,无须修改装饰者抽象类,只需继承装饰者抽象类,实现额外的一些装饰或者叫行为即可对被装饰者进行包装。
使用装饰器模式--------《模拟一个电话套餐选择场景》
创建套餐账单的基本信息-----需要被修饰 的抽象类
package order; public abstract class Order { String name; public String getOrder(){ return name; } public abstract int price(); }
创建基账单的信息类,未修饰时有自己的初始状态-----被修饰对象
package order; public class BuyOrder extends Order { public BuyOrder(){ name = "您选的套餐是:基本套餐"; } public String getOrder(){ return super.getOrder(); } public int price(){ return 10; } }
创建修饰基类-----一切修饰的扩展是在此基础上扩展的
package order; //额外套餐的基础类 public abstract class BuyOrder00 extends Order { public abstract String getOrder(); }
创建修饰类的扩展类------套餐的详细修饰情况(语音+流量+短信)
package order; public class BuyOrderNet extends BuyOrder00 { private Order order; public BuyOrderNet(Order order) { super(); this.order = order; } @Override public String getOrder() { return order.getOrder()+"+上流流量套餐"; } @Override public int price() { return order.price()+20; } } package order; public class BuyOrderTalk extends BuyOrder00 { private Order order; public BuyOrderTalk(Order order) { super(); this.order = order; } @Override public String getOrder() { return order.getOrder()+"+语音套餐"; } @Override public int price() { return order.price()+15; } } package order; public class BuyOrderMSG extends BuyOrder00 { private Order order; public BuyOrderMSG(Order order) { super(); this.order = order; } @Override public String getOrder() { return order.getOrder()+"+短信套餐"; } @Override public int price() { return order.price()+10; } }
测试用户选择的不同套餐情况
public class OrderTest { public static void main(String[] args) { Order order = new BuyOrder(); System.out.println(order.getOrder()+"\\t月资费是:"+order.price()); BuyOrder00 order1 = new BuyOrderTalk(order); System.out.println(order1.getOrder()+"\\t月资费是:"+order1.price()); BuyOrder00 order2 = new BuyOrderNet(order); System.out.println(order2.getOrder()+"\\t月资费是:"+order2.price()); BuyOrder00 order3 = new BuyOrderMSG(order); System.out.println(order3.getOrder()+"\\t月资费是:"+order3.price()); BuyOrder00 order4 = new BuyOrderMSG(order2); System.out.println(order4.getOrder()+"\\t月资费是:"+order4.price()); BuyOrder00 order5 = new BuyOrderMSG(order1); System.out.println(order5.getOrder()+"\\t月资费是:"+order5.price()); BuyOrder00 order6 = new BuyOrderNet(order1); System.out.println(order6.getOrder()+"\\t月资费是:"+order6.price()); BuyOrder00 order7 = new BuyOrderNet(new BuyOrderMSG(new BuyOrderTalk(order))); System.out.println(order7.getOrder()+"\\t月资费是:"+order7.price()); } }
运行结果
建议多打几个断点观察流程情况,一边更好的理解装饰器模式的工作流程
以上是关于java设计模式之 装饰器模式的主要内容,如果未能解决你的问题,请参考以下文章