使用包覆(Wrapper)的方式,可以动态地给物件增添新的功能,或是重新定义既有的功能,达到扩充目的。
当原本的程序需要配合需求新增功能,新功能之间彼此不互斥,可以叠加时。简单的做法是:
随着新功能功能不断地增加,简单的做法必须建立符合各种可能的物件,将导致管理不易。
因此,可以换个想法,让新功能包覆物件後形成新的物件,且新功能可以包覆其他新功能,如此一来,物件便拥有新功能。而管理上,只要确认包覆的顺序即可,减少推测多种可能结果的麻烦。
作法是:
本体物件,祖先代:Commuter
public class Commuter {
private String name;
private String destination;
public Commuter() {
}
public Commuter(String name, String destination) {
this.name = name;
this.destination = destination;
}
public void claimDestination() {
System.out.println("目的地: " + destination + " 已经抵达,准备下车");
}
public void commute() {
System.out.println("我是 " + name + ",是一位通勤者");
}
}
活动亲代,继承本体物件:Activity
public class Activity extends Commuter {
protected Commuter commuter;
public Activity() {
}
public Activity(Commuter commuter) {
this.commuter = commuter;
}
public void commuterDecorate(Commuter commuter) {
this.commuter = commuter;
}
@Override
public void claimDestination() {
if (commuter != null) {
commuter.claimDestination();
}
}
@Override
public void commute() {
if (commuter != null) {
commuter.commute();
}
}
}
活动子代:InADaze
、ListeningMusic
、ObservingOthers
、StopEverything
、WatchingYouTube
public class InADaze extends Activity {
public InADaze() {
}
public InADaze(Activity activity) {
super(activity);
}
public void dream() {
System.out.println("似乎想到什麽,让人想「A Ha」一下");
}
@Override
public void commute() {
super.commute();
System.out.println("什麽都不想做,发呆中");
dream();
}
}
public class ListeningMusic extends Activity {
public ListeningMusic() {
}
public ListeningMusic(Activity activity) {
super(activity);
}
public void feel() {
System.out.println("这首歌真赞啊");
}
@Override
public void commute() {
super.commute();
System.out.println("专注在听音乐");
feel();
}
}
public class ObservingOthers extends Activity {
public ObservingOthers() {
}
public ObservingOthers(Activity activity) {
super(activity);
}
public void alert() {
System.out.println("警戒中");
}
@Override
public void commute() {
super.commute();
alert();
System.out.println("观察他人的衣着、行为");
}
}
public class StopEverything extends Activity {
public StopEverything() {
}
public StopEverything(Activity activity) {
super(activity);
}
@Override
public void commute() {
super.commute();
System.out.println("停止一切事物");
}
}
public class WatchingYouTube extends Activity {
public WatchingYouTube() {
}
public WatchingYouTube(Activity activity) {
super(activity);
}
public void detail() {
System.out.println("这部影片可是今天的发烧啊");
}
@Override
public void commute() {
super.commute();
System.out.println("专注在 YT 上");
detail();
}
}
测试:CommuterDecoratorSample
public class CommuterDecoratorSample {
public static void main(String[] args) {
System.out.println("---第一位通勤者---");
Commuter victor = new Commuter("维特", "台北车站");
Activity watchingYouTube = new WatchingYouTube();
watchingYouTube.commuterDecorate(victor);
Activity stopEverything = new StopEverything(watchingYouTube);
stopEverything.commute();
stopEverything.claimDestination();
System.out.println("\n---第二位通勤者---");
Commuter sandy = new Commuter("珊迪", "市府站");
Activity listeningMusic = new ListeningMusic();
listeningMusic.commuterDecorate(sandy);
listeningMusic.commute();
listeningMusic.claimDestination();
System.out.println("\n---第三位通勤者---");
Commuter johnny = new Commuter("强尼", "象山站");
Activity inADaze = new InADaze(stopEverything);
inADaze.commuterDecorate(johnny);
Activity observingOthers = new ObservingOthers(inADaze);
observingOthers.commute();
observingOthers.claimDestination();
}
}
本体物件,祖先代:Commuter
class Commuter {
constructor(name, destination) {
this.name = name;
this.destination = destination;
}
claimDestination() {
console.log("目的地: " + this.destination + " 已经抵达,准备下车");
}
commute() {
console.log("我是 " + this.name + ",是一位通勤者");
}
}
活动亲代,继承本体物件:Activity
class Activity extends Commuter {
constructor(commuter) {
super(null, null);
this.commuter = commuter;
}
commuterDecorate(commuter) {
this.commuter = commuter;
}
/** @override */
claimDestination() {
if (this.commuter != null) {
this.commuter.claimDestination();
}
}
/** @override */
commute() {
if (this.commuter != null) {
this.commuter.commute();
}
}
}
活动子代:InADaze
、ListeningMusic
、ObservingOthers
、StopEverything
、WatchingYouTube
class InADaze extends Activity {
constructor(activity) {
super(activity);
}
dream() {
console.log("似乎想到什麽,让人想「A Ha」一下");
}
/** @override */
commute() {
super.commute();
console.log("什麽都不想做,发呆中");
this.dream();
}
}
class ListeningMusic extends Activity {
constructor(activity) {
super(activity);
}
feel() {
console.log("这首歌真赞啊");
}
/** @override */
commute() {
super.commute();
console.log("专注在听音乐");
this.feel();
}
}
class ObservingOthers extends Activity {
constructor(activity) {
super(activity);
}
alert() {
console.log("警戒中");
}
/** @override */
commute() {
super.commute();
this.alert();
console.log("观察他人的衣着、行为");
}
}
class StopEverything extends Activity {
constructor(activity) {
super(activity);
}
/** @override */
commute() {
super.commute();
console.log("停止一切事物");
}
}
class WatchingYouTube extends Activity {
constructor(activity) {
super(activity);
}
detail() {
console.log("这部影片可是今天的发烧啊");
}
/** @override */
commute() {
super.commute();
console.log("专注在 YT 上");
this.detail();
}
}
测试:commuterDecoratorSample
const commuterDecoratorSample = () => {
console.log("---第一位通勤者---");
const victor = new Commuter("维特", "台北车站");
const watchingYouTube = new WatchingYouTube();
watchingYouTube.commuterDecorate(victor);
const stopEverything = new StopEverything(watchingYouTube);
stopEverything.commute();
stopEverything.claimDestination();
console.log("\n---第二位通勤者---");
const sandy = new Commuter("珊迪", "市府站");
const listeningMusic = new ListeningMusic();
listeningMusic.commuterDecorate(sandy);
listeningMusic.commute();
listeningMusic.claimDestination();
console.log("\n---第三位通勤者---");
const johnny = new Commuter("强尼", "象山站");
const inADaze = new InADaze(stopEverything);
inADaze.commuterDecorate(johnny);
const observingOthers = new ObservingOthers(inADaze);
observingOthers.commute();
observingOthers.claimDestination();
};
commuterDecoratorSample();
Decorator 可以用俄罗斯娃娃来联想,每一次的包覆,除了维持既有功能之外,还能新增点什麽,好实践需求。但是,为了达成「有条有理」的继承、覆写、新增,必须在动手写程序码之前就定义好哪些行为可以扩充,这部分的设计复杂、不容易实践,可能到最後找不出共同点而罢休。
很明显地,Decorator 模式也是属於特殊要求下的解。
明天将介绍 Structural patterns 的第五个模式:Facade 模式。
<<: 【Day14-字串】浅谈python中最常用到的str处理方式——格式化、寻找、取代、分割、合并
>>: [GBC] 一个可以客制调整元件、支援通用渲染的Genero Client
铁人赛心得 这是第二次参加铁人赛,第一次主题是javasript的入门学习,第二次是比较有一点难度的...
第一天有讲到变数的部分,今天就让我们来深入了解一下吧! 首先,JAVA的资料型态可以分为原始资料型态...
既然今天是连假第二天,咱们今天来点简单的,把前面复习一下加一点新知识,整合一个有各种状态的按钮样式...
承接上一篇 实作 Rails-i18n语言选项在Bootstrap4 导览列,我们同样可以 在导览列...
答: 查对方电脑名称的条例有 DNS WINS NetBIOS over vpn tcp/ip LM...