现代人每个人基本都会有一部手机,有的有好几部,正常情况下买手机有很多套餐,比如裸机、裸机+贴膜、裸机+贴膜+手机壳等,但是不一定每个人在购买的时候都一定会贴膜,所以个性化需求就出来了,所以这个贴膜,总不能一出厂就有了,一般后续服务中增加的,属于装饰品,而装饰器模式就解决该问题。
定义:装饰器动态给一个对象添加一些额外的功能/职责,装饰模式比生成子类更为灵活。 抽象构件(component)角色 :用来规范被装饰的对象,一般为统一接口输出。具体构件(concreteComponent )角色 :被装饰的类,本身也是具备功能类。装饰(decorator)角色 :持有一个构件对象的实例。并定义一个跟抽象构件一致的接口。具体 (concreteDecorator ) 装饰角色 :负责给具体构件添加附加职责的类。在实际使用中多数情况下装饰角色和具体装饰角色可能由一个类来承担。其实也就是给你手机加些装饰器,而这些装饰器可有可无,根据你的选对来的,贴不贴膜,要不要手机壳,非原厂出厂就有。
对原有的对象或者功能动态增加功能/职责,很好的起到一个动态增删。并且代码不会浸入性低,新增的功能增减不会影响原来的功能;
就比如一部手机买到手是裸机,新贴上膜和手机壳,不会影响这个手机的使用,并且这个壳和膜不想用不会影响手机的功能。
代码易读:使用装饰器模式代码简单易读,业务逻辑清晰; 拓展性强:功能动态增删影响低; 减少耦合,低侵入:由于解决了传统的继承或者说在原来的对象去增加功能减少了很大的耦合和侵入性也很少;
多层装饰导致系统复杂:因为如果装饰器可以有好多层所以会导致系统过于复杂,所以建议不要过于复杂的装饰。
实现代码
/**
* @Auther: csh
* @Date: 2020/5/28 18:02
* @Description:抽象的手机
*/
public interface IPhone {
//打电话
void callUp(String number);
//上网
void internet(int newWork);
//基本功能
void printFunction();
}
/**
* @Auther: csh
* @Date: 2020/5/28 18:06
* @Description:小米手机
*/
public class XMPhone implements IPhone {
@Override
public void callUp(String number) {
System.out.println("小米手机打电话:"+number);
}
@Override
public void internet(int newWork) {
System.out.println("上的网络"+newWork+"G");
}
@Override
public void printFunction() {
System.out.println("小米手机有手电话和上网功能");
}
}
/**
* @Auther: csh
* @Date: 2020/5/28 18:05
* @Description:华为手机
*/
public class HWPhone implements IPhone {
@Override
public void callUp(String number) {
System.out.println("正在打电话:"+number);
}
@Override
public void internet(int newWork) {
System.out.println("上的网络"+newWork+"G");
}
@Override
public void printFunction() {
System.out.println("华为手机有手电话和上网功能");
}
}
/**
* @Auther: csh
* @Date: 2020/5/28 18:07
* @Description:抽象的修饰器
*/
public abstract class IPhoneDecorator implements IPhone {
protected IPhone phone;
public IPhoneDecorator(IPhone phone) {
this.phone = phone;
}
@Override
public void printFunction() {
phone.printFunction();
}
}
/**
* @Auther: csh
* @Date: 2020/5/28 18:10
* @Description:手机壳装饰器
*/
public class PhoneShellDecorator extends IPhoneDecorator {
public PhoneShellDecorator(IPhone phone) {
super(phone);
}
@Override
public void callUp(String number) {
phone.callUp(number);
}
@Override
public void internet(int newWork) {
phone.internet(newWork);
}
@Override
public void printFunction() {
super.printFunction();
this.setShell();
}
private void setShell(){
System.out.println("加装了手机壳");
}
}
/**
* @Auther: csh
* @Date: 2020/5/28 18:10
* @Description:
*/
public class PhoneFilmDecorator extends IPhoneDecorator {
public PhoneFilmDecorator(IPhone phone) {
super(phone);
}
@Override
public void callUp(String number) {
phone.callUp(number);
}
@Override
public void internet(int newWork) {
phone.internet(newWork);
}
@Override
public void printFunction() {
super.printFunction();
this.setFilm();
}
private void setFilm(){
System.out.println("贴了膜");
}
}
/**
* @Auther: csh
* @Date: 2020/5/28 18:16
* @Description:案例
*/
public class Client {
public static void main(String[] args) {
HWPhone hwPhone = new HWPhone();
hwPhone.printFunction();
PhoneFilmDecorator phoneFilmDecorator = new PhoneFilmDecorator(hwPhone);
XMPhone xmphone = new XMPhone();
phoneFilmDecorator.printFunction();
PhoneShellDecorator phoneShellDecorator = new PhoneShellDecorator(xmphone);
phoneShellDecorator.printFunction();
}
}
华为手机有手电话和上网功能
华为手机有手电话和上网功能
贴了膜
小米手机有手电话和上网功能
加装了手机壳
装饰器在日常开发过程中应用广泛,比如类似这种需求迭代比较快,而又不确定这个属性/方法是否以后会一直保留,在这种不确定性的场景下装饰器再适合不过了。或者说原来的功能已很稳定不想影响到原来的功能,并且该功能只是个性化给某个需求专用,那就建议使用。