装饰模式(Decorator Pattern)
动态给对象增加功能,从一个对象的外部来给对象添加功能,相当于改变了对象的外观,比用继承的方式更加的灵活。
允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
优点:
-
装饰者模式比继承灵活性,在不改变原有对象的情况下给对象扩展功能,符合开闭原则。继承关系是静态的,在编译的时候就已经决定了行为,不便于控制增加行为的方式和时机。
-
装饰者模式可以动态使用不同的装饰类排列组合,创造出多样的行为组合。
缺点:
-
1.装饰模式会导致设计出大量的ConcreteDecorator类,增加系统的复杂性。
-
2.对于多次装饰的对象,一旦出现错误,排错繁琐;
应用场景:
装饰模式通常在以下几种情况使用。
-
当需要给一个现有类添加附加职责,而又不能采用生成子类的方法进行扩充时。例如,该类被隐藏或者该类是终极类或者采用继承方式会产生大量的子类。
-
当需要通过对现有的一组基本功能进行排列组合而产生非常多的功能时,采用继承关系很难实现,而采用装饰模式却很好实现。
-
当对象的功能要求可以动态地添加,也可以再动态地撤销。
可大致分成三个部分:原有对象、添加职责、具体职责
通过继承关系添加职责
代码实现:
Component组成部分
public abstract class Component {
public abstract void Operation(); //实施
}
Decorator装饰类
abstract class Decorator extends Component {
protected Component component; //只声明,不时例
public void SetComponent(Component component){
this.component = component;
}
@Override
public void Operation() {
if (component != null){
component.Operation();
}
}
}
装饰模式Person类(ConcreteComponent)具体成员
*/
public class Person {
private String name;
public Person() {
}
public Person(String name) {
this.name = name;
}
public void show() {
System.out.println("装扮的" + name);
}
}
服饰抽象类(Decorator)
public class Finery extends Person { //服饰
protected Person component;
// 打扮
public void Decorate(Person component){
this.component = component;
}
// 重写方法
@Override
public void show() {
// super.show();
if (component != null){
component.show();
}
}
}
具体服饰BigTrouser
public class BigTrouser extends Finery {
@Override
public void show() {
System.out.println("大垮裤");
super.show();
}
}
具体服饰TShirts
public class TShirts extends Finery{
@Override
public void show() {
System.out.println("大T恤");
super.show();
}
}
具体服饰Sneakers
public class Sneakers extends Finery {
@Override
public void show() {
System.out.println("破球鞋");
super.show();
}
}
具体服饰Suit
public class Suit extends Finery {
@Override
public void show() {
System.out.println("西装");
super.show();
}
}
具体服饰Tie
public class Tie extends Finery {
@Override
public void show() {
System.out.println("领带");
super.show();
}
}
具体服饰LeatherShoes
public class LeatherShoes extends Finery {
@Override
public void show() {
System.out.println("皮鞋");
super.show();
}
}
客户端
public class Client {
public static void main(String[] args) {
Person xc = new Person("小蔡");
System.out.println("\n第一种装扮:");
TShirts dtx = new TShirts();
BigTrouser kk = new BigTrouser();
Sneakers pqx = new Sneakers();
dtx.Decorate(xc);
kk.Decorate(dtx);
pqx.Decorate(kk);
pqx.show();
System.out.println("\n第二种装扮:");
LeatherShoes px = new LeatherShoes();
Tie ld = new Tie();
Suit xz = new Suit();
px.Decorate(xc);
ld.Decorate(px);
xz.Decorate(ld);
xz.show();
}
}
责任链(Chain of Responsibility)
模式的定义:为了避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。
注意:责任链模式也叫职责链模式。
在责任链模式中,客户只需要将请求发送到责任链上即可,无须关心请求的处理细节和请求的传递过程,所以责任链将请求的发送者和请求的处理者解耦了。
责任链模式是一种对象行为型模式,
其主要优点如下:
-
降低了对象之间的耦合度。该模式使得一个对象无须知道到底是哪一个对象处理其请求以及链的结构,发送者和接收者也无须拥有对方的明确信息。
-
增强了系统的可扩展性。可以根据需要增加新的请求处理类,满足开闭原则。
-
增强了给对象指派职责的灵活性。当工作流程发生变化,可以动态地改变链内的成员或者调动它们的次序,也可动态地新增或者删除责任。
-
责任链简化了对象之间的连接。每个对象只需保持一个指向其后继者的引用,不需保持其他所有处理者的引用,这避免了使用众多的 if 或者 if···else 语句。
-
责任分担。每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。
其主要缺点如下:
-
不能保证每个请求一定被处理。由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理。
-
对比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。
-
职责链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于职责链的错误设置而导致系统出错,如可能会造成循环调用。
应用场景:
-
有多个对象可以处理一个请求,哪个对象处理该请求由运行时刻自动确定。
-
可动态指定一组对象处理请求,或添加新的处理者。
-
在不明确指定请求处理者的情况下,向多个处理者中的一个提交请求。
归结起来就是传递请求、处理请求
代码实现:
可以看到客户端都是“jingli”发起,但是最后输出的管理者按照职责范围层层递进,由对应管理者审批
管理者(抽象类)
abstract class Manager {
protected String name;
protected Manager superior; //管理者的上级
public Manager(String name) {
this.name = name;
}
// 设置管理者的上级
public void SetSuperior(Manager superior){
this.superior = superior;
}
// 申请请求
abstract public void RequestApplications(Request request);
}
申请
public class Request {
// 申请类别
private String requestType;
public String getRequestType () {
return requestType;
}
public void setRequestType (String requestType){
this.requestType = requestType;
}
// 申请内容
private String requestContent;
public String getRequestContent() {
return requestContent;
}
public void setRequestContent(String requestContent) {
this.requestContent = requestContent;
}
// 数量
private int number;
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public Request() {
}
public Request(String requestType, String requestContent, int number) {
this.requestType = requestType;
this.requestContent = requestContent;
this.number = number;
}
}
经理
class CommonManager extends Manager{
public CommonManager(String name) {
super(name);
}
@Override
public void RequestApplications(Request request) {
if (request.getRequestType().equals("请假") && request.getNumber() <= 2) {
System.out.println(name + ": "+ request.getRequestContent()+"数量:"+request.getNumber()+" 被批准");
}else {
if (superior != null) //其余申请转到上级
superior.RequestApplications(request);
}
}
}
总监
class Majordomo extends Manager{
public Majordomo(String name) {
super(name);
}
@Override
public void RequestApplications(Request request) {
if (request.getRequestType().equals("请假" ) && request.getNumber() <= 5) {
System.out.println(name + ": "+ request.getRequestContent()+"数量:"+request.getNumber()+" 被批准");
}else {
if (superior != null) //其余申请转到上级
superior.RequestApplications(request);
}
}
}
总经理
class GeneralManager extends Manager {
public GeneralManager(String name) {
super(name);
}
@Override
public void RequestApplications(Request request) {
if (request.getRequestType().equals("请假" ) ) { //总经理可以准许下属任意天数的假期
System.out.println(name + ": "+ request.getRequestContent()+"数量:"+request.getNumber()+" 被批准");
}else if(request.getRequestType().equals("加薪") && request.getNumber() <= 500){ //总经理可以准许下属500以内加薪
System.out.println(name + ": "+ request.getRequestContent()+"数量:"+request.getNumber()+" 被批准");
}else if (request.getRequestType().equals("加薪") && request.getNumber() > 500){ //超过500考虑一下
System.out.println(name + ": "+ request.getRequestContent()+"数量:"+request.getNumber()+" 再说吧");
}
}
}
客户
public class Test {
public static void main(String[] args) {
CommonManager jinli = new CommonManager("金利");
Majordomo zongjian = new Majordomo("宗剑");
GeneralManager zhongjingli = new GeneralManager("钟精励");
jinli.SetSuperior(zongjian); //指定对象上级
zongjian.SetSuperior(zhongjingli);
Request request = new Request();
request.setRequestType("请假");
request.setRequestContent("小蔡请假");
request.setNumber(1);
jinli.RequestApplications(request);
Request request2 = new Request();
request2.setRequestType("请假");
request2.setRequestContent("小蔡请假");
request2.setNumber(4);
jinli.RequestApplications(request2);
Request request3 = new Request();
request3.setRequestType("加薪");
request3.setRequestContent("小蔡请求加薪");
request3.setNumber(500);
jinli.RequestApplications(request3);
Request request4 = new Request();
request4.setRequestType("加薪");
request4.setRequestContent("小蔡请求加薪");
request4.setNumber(800);
jinli.RequestApplications(request4);
}
}
异同点:
- 最低层都是封装继承和多态的运用
- 装饰者模式在创建对象时是父类身份 子类对象,职责链模式在创建对象时是父类身份 父类对象,但最后穿进来都是子类对象,二者本质上并无不同
- 职责链模式实现了请求者和处理者的松耦合。动态组合职责。比状态模式耦合度更低,更加灵活。可以随时地增加或修改处理一个请求地结构。增强了给对象指派职责地灵活性。