装饰模式(IO设计的核心思想)
装饰模式的定义:在不影响原对象的前提下,无入侵的给一个对象增一些额外的功能。
换句话就是:装饰模式就是对原对象进行包装,使之具有其不具备的功能。但这些功能是在原有功能的基础上进行增强的。
例如这个使用场景:现在苹果出了12了,每一代苹果都是继承自上代苹果的。那么我要增加一些2代苹果的功能,我可以直接直接在2代的类上加功能吗?答案是肯定不可以的一是因为其巨大的调用关系与函数,再者就是其派生类怎么办?所以装饰者模式就是解决对象链中的其中某个对象功能的扩增。
这是其一,其二是如果类的跨度特别大,我只需要这两个跨度大的类,那么在其中的中间类是非常多的,会形成子类膨胀。装饰模式就是解决子类膨胀的一种方法。
综上:装饰者模式可以解决两种问题:
- 子类膨胀。
- 将对象链中的对象单独拆出来进行功能扩展,而不用担心其派生类。
例如:文件可以作为字符串的扩展:new File(“d:/abc.txt”);
原字符串没有影响,给原有对象字符串增加额外的功能(作为文件的功能)
Java中的装饰器模式
再例如:流可以作为文件的扩展:new FileInputStream(new File(“d:/abc.txt”));
从上述可以看出装饰模式需要两个对象:被装饰对象、装饰对象。(与java中的设计相同可以设计一个接口与实现类)
例如实例:手机被智能手机装饰。
值得注意的是:装饰者要装饰一个对象必然要持有该对象的引用。
public interface IPhone{
void call();
}
public class PhoneImpl{
public void call(){
}
}
public abstract class SmartPhone implements Phone{
//设计为抽象类是因为再类中需要一个被装饰的引用。实现被引用对象的接口是因为要在原有对象的基础上(增加功能)
IPhone iphone;
public SmartPhone(){}
public SmartPhone(IPhone iphone){
this.iphone = iphone;
}
//原电话的功能
public void call(){
iphone.call();
}
}
抽象类中包含被装饰对象的引用,并且实现、调用其原有方法。功能的增加可以用其派生类增加,不同功能派生不同派生类。
public class ConcreteSmartPhone1 extends SmartPhone{
public ConcreteSmartPhone1(Phone phone){
super(phone);
}
public void call(){
super.call();
this.changeBackground();
//在原有功能的基础上进行增强
}
public void changeBackground(){
System.out.print("改变背景颜色");
}
}
public class ConcreteSmartPhone2 extends SmartPhone{
public ConcreteSmartPhone1(Phone phone){
super(phone);
}
public void call(){
super.call();
this.changeSize();
//在原有功能的基础上进行增强
}
public void changeSize(){
System.out.print("改变尺寸");
}
}
Python中的装饰器模式
- 在python中,装饰器是用来包装函数的函数
- 装饰器常用于下列情况:
- 将多个函数中的重复代码拿出来整理成一个装饰器
- 对多个函数的共同功能进行处理
在python中装饰器的定义方式如下:
def decorator(func):
pass
@decorator
def func():
pass
decorator是一个装饰器。func是被装饰的函数。
例如这样一个场景:我想知道一个项目中的各个函数的执行时间,**我总不可能把每个函数都添加一遍代码吧?**这时就可以使用装饰器。
import time
def deco(func):
def dothat():
print("star time:", time.ctime())
func()
print("end time:", time.ctime())
return "deco end!"
return dothat
@deco
def func():
print("i am a func")
print(func())
star time: Wed Sep 29 19:03:41 2021
i am a func
end time: Wed Sep 29 19:03:41 2021
deco end!
装饰器就是闭包的应用。
func
被deco
装饰了,在func
的时候就相当于deco(func)
了,然后返回了dothat
函数,加()
被执行。
import time
def deco(func):
def dothat():
print("star time:", time.ctime())
func()
print("end time:", time.ctime())
return dothat
@deco
def func():
print("i am a func")
print(func)
<function __main__.deco.<locals>.dothat()>