装饰模式
装饰模式在中国使用的那实在是多,中国的文化是中庸文化,说话或做事情都不能太直接,需要
有技巧的,比如说话吧,你要批评一个人,你不能一上来就说你这个做的不对,那个做的不对,你要先肯
定他的成绩,表扬一下优点,然后再指出瑕疵,指出错误的地方,最后再来个激励,你修改了这些缺点后
有那些好处,比如你能带更多的小兵,到个小头目等等,否则你一上来就是一顿批评,你瞅瞅看,肯定是
不服气,顶撞甚至是直接“此处不养爷,自有养爷处”开溜哇。
我们不说不开心的事情,今天举一个什么例子呢?就说说我上小学的的糗事吧。我上小学的时候学习
成绩非常的差,班级上 40 多个同学,我基本上都是在排名 45 名以后,按照老师给我的定义就是“不是读
书的料”,但是我老爸管的很严格,明知道我不是这块料,还是往赶鸭子上架,每次考试完毕我都是战战兢
兢的,“竹笋炒肉”是肯定少不了的,能少点就少点吧,肉可是自己的呀。四年级期末考试考完,学校出来
个很损的招儿(这招儿现在很流行的),打印出成绩单,要家长签字,然后才能上五年级,我那个恐惧呀,
不过也就是几秒钟的时间,玩起来什么都忘记了。
package com.the151suggestions.part7;
/**
* Created by wanggs on 2017/7/24.
* 装饰模式
*/
public class S1070 {
public static void main(String[] args) {
// 老爸开始看成绩单,这个成绩单可是最真实的,啥都没有动过,原装,看 Father 类:
//成绩单拿过来
SchoolReport sr = new FouthGradeSchoolReport();
//看成绩单
sr.report();
//签名?休想
System.out.println("*************************");
//美化过的成绩单拿过来
SchoolReport src = new SugarFouthGradeSchoolReport();
src.report();
src.sign("老鼠");
//成绩单拿过来
SchoolReport srr;
sr = new FouthGradeSchoolReport(); //原装的成绩单
//加 了最高分说明的成绩单
srr = new HighScoreDecorator(sr);
//又加了成绩排名的说明
srr = new SortDecorator(srr);
//看成绩单
srr.report();
//然后老爸,一看,很开心,就签名了
srr.sign("老三"); //我叫小三,老爸当然叫老三
}
}
/**
* 成绩单抽象类
*/
abstract class SchoolReport {
//成绩单的主要展示的就是你的成绩情况
public abstract void report();
//成绩单要家长签字,这个是最要命的
public abstract void sign(String name);
}
/**
* 四年级的成绩单,这个是我们学校第一次实施,以前没有干过
* 这种“缺德”事。
*/
class FouthGradeSchoolReport extends SchoolReport {
// 我的成绩单
@Override
public void report() {
//成绩单的格式是这个样子的
System.out.println("尊敬的XXX家长:");
System.out.println(" ......");
System.out.println(" 语文 62 数学65 体育 98 自然 63");
System.out.println(" .......");
System.out.println(" 家长签名: ");
}
public void sign(String name) {
System.out.println("家长签名为: " + name);
}
}
/**
* 对这个成绩单进行美化
* Sugar这个词太好了,名词是糖的意思,动词就是美化
* 给你颗糖你还不美去
*/
class SugarFouthGradeSchoolReport extends FouthGradeSchoolReport {
//首先要定义你要美化的方法,先给老爸说学校最高成绩
private void reportHighScore() {
System.out.println("这次考试语文最高是75,数学是78,自然是80");
}
//在老爸看完毕成绩单后,我再汇报学校的排名情况
private void reportSort() {
System.out.println("我是排名第38名...");
}
//由于汇报的内容已经发生变更,那所以要重写父类
@Override
public void report() {
this.reportHighScore(); //先说最高成绩
super.report(); //然后老爸看成绩单
this.reportSort(); //然后告诉老爸学习学校排名
}
}
/**
* 老爸听我汇报最高成绩后,就直接乐开花了,直接签名了,后面的排名就没必要了,或者老爸要先听排名情况,
* 那怎么办?继续扩展类?你能扩展多少个类?这还是一个比较简单的场景,一旦需要装饰的条件非常的多,比如
* 20 个,你还通过继承来解决,你想想的子类有多少个?你是不是马上就要崩溃了!
*/
//装饰类,我要把我的成绩单装饰一下
//Decorator 抽象类的目的很简单,就是要让子类来对封装 SchoolReport 的子类,怎么封装?
abstract class Decorator extends SchoolReport {
//首先我要知道是那个成绩单
private SchoolReport sr;
//构造函数,传递成绩单过来
public Decorator(SchoolReport sr) {
this.sr = sr;
}
//成绩单还是要被看到的
public void report() {
this.sr.report();
}
//看完毕还是要签名的
public void sign(String name) {
this.sr.sign(name);
}
}
// 我要把我学校的最高成绩告诉老爸
class HighScoreDecorator extends Decorator {
public HighScoreDecorator(SchoolReport sr) {
super(sr);
}
//我要汇报最高成绩
private void reportHighScore() {
System.out.println("这次考试语文最高是75,数学是78,自然是80");
}
//最高成绩我要做老爸看成绩单前告诉他,否则等他一看,就抡起笤帚有揍我,我那还有机会说呀
@Override
public void report() {
this.reportHighScore();
super.report();
}
}
//学校排名的情况汇报
class SortDecorator extends Decorator{
public SortDecorator(SchoolReport sr) {
super(sr);
}
//告诉老爸学校的排名情况
private void reportSort(){
System.out.println("我是排名第38名...");
}
//老爸看完成绩单后再告诉他,加强作用
@Override
public void report(){
super.report();
this.reportSort();
}
}
反射增加装饰者的普适性
package com.the151suggestions.part7;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
/**
* Created by wanggs on 2017/7/24.
* 使用反射增加装饰者的普适性
* 让小老鼠更加强大
* 此类代码是比较通用的装饰着模式, 只需定义被装饰的类级装饰类即可, 装饰行为由动态代理实现, 实现了对装饰类和被装饰类的解耦
*/
public class S107 {
public static void main(String[] args) {
Animal jetty = new Rat();
// 为jetty增加飞行能力
jetty = new DecorateAnimal(jetty,FlyFeature.class);
// 增加挖地能力
jetty = new DecorateAnimal(jetty,DigFeature.class);
// 耍猫
jetty.doStuff();
}
}
interface Animal {
public void doStuff();
}
// 老鼠
class Rat implements Animal {
@Override
public void doStuff() {
System.out.println("Jetty will play Tom");
}
}
// 定义某种功能
interface Feature {
// 加载特性
public void load();
}
// 飞行能力
class FlyFeature implements Feature {
@Override
public void load() {
System.out.println("增加一双翅膀....");
}
}
// 钻地能力
class DigFeature implements Feature {
@Override
public void load() {
System.out.println("增加钻地能力....");
}
}
// 包装类
class DecorateAnimal implements Animal {
// 包装动物
private Animal animal;
// 使用哪一个包装器
private Class extends Feature> clz;
public DecorateAnimal(Animal animal, Class extends Feature> clz) {
this.animal = animal;
this.clz = clz;
}
@Override
public void doStuff() {
// 匿名
InvocationHandler handler = new InvocationHandler() {
// 包装具体行为
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object object = null;
// 设置包装条件
if (Modifier.isPublic(method.getModifiers())) {
object = method.invoke(clz.newInstance(), args);
}
animal.doStuff();
return object;
}
};
// 当前类加载器
ClassLoader classLoader = getClass().getClassLoader();
// 动态代理,由Handler决定如何包装
Feature proxy = (Feature) Proxy.newProxyInstance(classLoader, clz.getInterfaces(), handler);
proxy.load();
}
}