您的位置:首页 > 编程语言 > Java开发

大话设计模式--java实现装饰者设计模式与补充

2017-10-26 19:39 435 查看
直接用《大话设计模式这本书》里面的例子,小菜写一个可以给人搭配不同的服饰的系统。比如程序员,服饰是穿t-shirt,穿大裤衩,穿运动鞋。管理类白领则是穿西装,打领带,穿皮鞋。然后人都有个形象展示的方法。

这本书里面用的是c#,但是跟java差距不大,这里都改为了java代码。

public class Person {
private String profe;//职业

public Person(String profe){
this.profe = profe;
}
public void show(){
System.out.println("装扮的" + profe);
}
public void wearTShirt(){
System.out.println("穿T-Shirt ");
}

public void wearBigPant(){
System.out.println("穿大裤衩 ");
}

public void wearSneaker(){
System.out.println("穿运动鞋 ");
}

public void wearBusinessSuit(){
System.out.println("穿西装 ");
}

public void wearTie(){
System.out.println("打领带 ");
}

public void wearshoes(){
System.out.println("穿皮鞋 ");
}
}
测试
public class TestCase1 {
public static void main(String[] args) {
Person person = new Person("programmer");
person.show();
person.wearTShirt();
person.wearBigPant();
person.wearSneaker();
System.out.println("======================");
Person person2 = new Person("manager");
person2.show();
person2.wearBusinessSuit();
person2.wearTie();
person2.wearshoes();
}
}
输出
装扮的programmer
穿T-Shirt
穿大裤衩
穿运动鞋
======================
装扮的manager
穿西装
打领带
穿皮鞋


咋一看似乎挺好的,但是如果又新增了一类人呢,比如工人,穿着肯定不一样啊,根据开放-封闭原则(对于拓展是开放的,对于修改是封闭的),我们肯定不能在原来的类里面添加新的方法。

这时,一般会跟小菜一样,考虑继承吧。人为单独一个类,让各种服饰继承服饰这个类实现show方法。

public class Person {
private String profe;//职业

public Person(String profe){
this.profe = profe;
}
public void show(){
System.out.println("装扮的" + profe);
}
}

/**
* 所有服饰类的父类
* @author 12706
*
*/
public abstract class Custom {
public abstract void show();
}

public class TShirt extends Custom {

@Override
public void show() {
System.out.println("穿T-Shirt ");
}
}

public class BigPant extends Custom{

@Override
public void show() {
System.out.println("穿大裤衩 ");
}

}

public class Sneaker extends Custom{

@Override
public void show() {
System.out.println("穿运动鞋 ");
}

}
白领穿的略..


测试
public class TestCase {
public static void main(String[] args) {
Person person1 = new Person("programmer");
TShirt ts = new TShirt();
BigPant bp = new BigPant();
Sneaker sn = new Sneaker();
person1.show();
ts.show();
bp.show();
sn.show();
System.out.println("==============");
Person person2 = new Person("manager");
BusinessSuit bs = new BusinessSuit();
Tie tie = new Tie();
Shoes shoes = new Shoes();
person2.show();
bs.show();
tie.show();
shoes.show();
}
}
输出
装扮的programmer
穿T-Shirt
穿大裤衩
穿运动鞋
==============
装扮的manager
穿西装
打领带
穿皮鞋


很显然也实现了,但是按照大鸟说的,为什么要一个一个show啊,就好像在众目睽睽下一件一件穿衣服,所以我们在内部就构造好,而且穿衣服不能乱穿要讲顺序。这时可以使用装饰者设计模式(动态地给一个对象添加一些额外的功能)。



Component:定义一个对象接口,可以给这些对象动态添加职责(功能);

ConcreteComponent:是Component的一个具体实现对象,当然可以给这个对象添加一些职责;

Decrator:装饰抽象类,继承了Component,从外类来扩展了Component类的功能,但是对Component类来说,是不需要知道它的存在的。

ConcreteComponentA和ConcreteComponentB:是具体的装饰类的实现,起到了给Component添加功能的作用。

下面使用该模式来实现上面穿衣的功能

public class Person {

private String profe;

public Person(){}

public Person(String profe){
this.profe = profe;
}
public void show(){
System.out.println("装扮的" + profe);
}

}

public class Custom extends Person{
//内部持有一个Person对象,它是被用来装饰的
protected Person person;

public Custom(Person person){
this.person = person;
}
@Override
public void show(){
person.show();
}

}
//TShirt类继承服饰类,实现功能穿t-shirt
public class TShirt extends Custom {

public TShirt(Person person) {
super(person);
}

@Override
public void show() {
System.out.println("穿T-Shirt ");
super.show();
}

}
public class BigPant extends Custom{

public BigPant(Person person) {
super(person);
}

@Override
public void show() {
System.out.println("穿大裤衩 ");
super.show();
}
}
public class Sneaker extends Custom{

public Sneaker(Person person) {
super(person);
}

@Override
public void show() {
System.out.println("穿运动鞋 ");
super.show();
}

}
//白领穿衣的三个类略...


测试
public class TestCase {
public static void main(String[] args) {
Person person1 = new Person("programmer");
Sneaker sn = new Sneaker(person1);
BigPant bp = new BigPant(sn);
TShirt ts = new TShirt(bp);
ts.show();
System.out.println("============================");
Person person2 = new Person("manager");
BusinessSuit bs = new BusinessSuit(new Tie(new Shoes(person2)));
bs.show();

}
}
输出
穿T-Shirt
穿大裤衩
穿运动鞋
装扮的programmer
============================
穿西装
打领带
穿皮鞋
装扮的manager


注:如果不能理解服饰的子类重写的方法中使用super.show()的调用的话,那么改成person.show()也是一样的。

就是服饰下面持有个人对象,我们来给他穿衣服,套上TShirt后(将对象传入构造方法),那么调用show的方法的就是调用了穿衣的show方法,接着会继续调用传入的person对象的show方法,比如传给TShirt的是一个穿了大裤衩的Person呢,那么肯定就再调用BigPant的show方法了。

装饰者设计模式把每个要装饰的功能放在单独的类中,并让这个类包装它所要的对象,因此,当需要执行特殊行为时,客户代码就可以在根据运行时根据需要有选择地、按照顺序地使用装饰功能包装对象了。

我觉得明显的好处就是,它把类中的装饰功能从类中搬移出去,写成一个单独的具有特定功能的类。

在java中最常见的就是流中的使用了,一个字符流包装一个转换流再包装一个字节流。

下面使用,爱奇艺视频用户名,老公爱红牛的例子来说明装饰者设计模式。

每个女生都有很多属性,颜值,智商,以及姓名,还有说话的方法。

一般大家都是普通的女人。颜值一般,但是可以化妆来提高颜值,智商一般但是可以通过教育来提高,当然礼貌的人说话方式很好。

public class Women {

private String name;
private int beauty;
private int iq;

public Women() {}

public Women(String name, int beauty, int iq) {
this.name = name;
this.beauty = beauty;
this.iq = iq;
}
public void say(){
System.out.println("我的名字叫:" + name);
}
get、set方法
}

public class WrappedWomen extends Women{

protected Women women;

public WrappedWomen(Women women) {
//      初始化父类
this.women = women;
}
@Override
public void say(){
System.out.print("我的名字叫:" + women.getName());
}

@Override
public int getBeauty() {
return women.getBeauty();
}

@Override
public int getIq() {
return women.getIq();
}
@Override
public String getName(){
return women.getName();
}
}


下面是几个子类

public class DressedWomen extends WrappedWomen{

public DressedWomen(Women women) {
super(women);
}

@Override
public int getBeauty() {
//原来的颜值+20
return women.getBeauty()+20;
}
}

public class EducatedWomen extends WrappedWomen{

public EducatedWomen(Women women) {
super(women);
}
@Override
public int getIq(){
//原来的iq+20
return women.getIq()+20;
}
}

public class PoliteWomen extends WrappedWomen{

public PoliteWomen(Women women) {
super(women);
}
@Override
public void say(){
System.out.print("大家好");
women.say();
System.out.println("请多关照");
}

}
测试:
public class TestCase {
public static void main(String[] args) {
Women women = new Women("Me", 60, 100);
WrappedWomen ww = new WrappedWomen(women);
PoliteWomen pw = new PoliteWomen(new EducatedWomen(new DressedWomen(ww)));
System.out.println("颜值:"+pw.getBeauty());
pw.say();
System.out.println("智商:"+pw.getIq());
}
}
输出
颜值:80
大家好我的名字叫:Me请多关照
智商:120


可以看到一个化妆了受教育又有礼貌的人跟初始传入的属性完全不一样。同样在每个子类礼貌使用了woman.xx,也可以使用super.xx



比如获取颜值吧,那么根据图,考虑下走向吧。如果深入感觉只会转到牛角尖,尽量用person吧容易理解些。

由于一般我们考虑面向接口编程。那么来个接口模式的装饰者吧

/**
* 模拟DNF
* 鬼剑士转职有四个职业   剑魂,狂战士(俗称红狗),鬼泣,阿修罗
* 抽象类  鬼剑士 可以写四个实现类
* 商城有时装,鞋子加移动  上衣加攻击   下装加血量...
* @author 12706
*
*/
public interface Swordman {

public void attack();//进攻

public void defense();//防御

public void escape();//逃跑
}

public class RedDog implements Swordman{

public void attack() {
System.out.println("红狗释放大蹦,输出1000");
}

public void defense() {
System.out.println("红狗防守,防御1000");
}

public void escape() {
System.out.println("红狗逃跑,移动1000");
}

}

public class SwordmanJeans extends TransferSwordman{

public SwordmanJeans(Swordman man) {
super(man);
}

@Override
public void defense() {
man.defense();
System.out.println("穿了裤子,血量加厚400");
}
}

public class SwordmanTShirt extends TransferSwordman{

public SwordmanTShirt(Swordman man) {
super(man);
}

@Override
public void attack() {
man.attack();
System.out.println("穿了上衣,攻击力加1000");
}
}

public class SwordmanShoes extends TransferSwordman{

public SwordmanShoes(Swordman man) {
super(man);
}

@Override
public void escape() {
man.escape();
System.out.println("穿了鞋子,移动加500");
}
}

测试
public class TestCase {
public static void main(String[] args) {
RedDog rd = new RedDog();
SwordmanJeans sword = new SwordmanJeans(new SwordmanShoes(new SwordmanTShirt(rd)));
sword.attack();
sword.defense();
sword.escape();
}
}

输出
红狗释放大蹦,输出1000
穿了上衣,攻击力加1000
红狗防守,防御1000
穿了裤子,血量加厚400
红狗逃跑,移动1000
穿了鞋子,移动加500
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: