美文网首页
装饰器模式(Decoretor Pattern)

装饰器模式(Decoretor Pattern)

作者: 吉他手_c156 | 来源:发表于2020-04-17 00:13 被阅读0次

装饰器模式(decoretor pattern)也称为包装器模式(wrapper pattern),是指在不改变原有对象的基础上,动态的将功能附加到对象上,属于结构型模式

装饰器的结构与特点

装饰器模式主要包含以下角色

1.抽象构建(Component)角色,定义抽象构建规定具体构建要实现的方法
2.具体构建(Concrete Component)角色,实现抽象构建,使用装饰器为其添加一些职责
3.抽象装饰(Decoretor)角色,继承抽象构建,并包含具体构建的实例,扩展具体构建的功能
4.具体装饰(Concrete Decoretor)角色,实现抽象装饰,并给具体构建添加扩展的责任

装饰器模式的优缺点

优点
1.采用装饰器扩展对象的功能比继承更灵活
2.可以设计出不同的具体装饰类,创造出多个不同的行为组合
缺点
1.装饰模式增加了许多子类,如果过度使用会增加系统的复杂度

装饰器模式的应用

创建抽象构建,规定具体构建要实现的方法

/**
 * Componetn 规定具体构建要实现的方法
 */
public abstract class BatterCake {

    public abstract String getMsg();
    public abstract int price();
}

创建具体构建,实现抽象构建的方法

/**
 * 具体构建 Concrete Component 实现抽象构建的方法,使用装饰器为其附加职责
 */
public class BaseBatterCake extends BatterCake {

    @Override
    public String getMsg() {
        return "煎饼";
    }

    @Override
    public int price() {
        return 5;
    }
}

创建抽象装饰器,继承具体构建,并包含具体构建的引用,规定子类必须实现的构造方法,这里的方法不做实现,引用具体构建的方法

/**
 * 抽象装饰器 Decoretor 这是继承抽象构建,并包含具体构件的实例
 * 这里的方法不做具体实现,调用被装饰类的方法
 */
public class BatterCakeDecoretor extends BatterCake{

    private BatterCake batterCake;

    // 规定子类必须实现的构造方法
    public BatterCakeDecoretor(BatterCake batterCake){
        this.batterCake = batterCake;
    }

    @Override
    public String getMsg() {
        return this.batterCake.getMsg();
    }

    @Override
    public int price() {
        return this.batterCake.price();
    }
}

创建具体装饰器实现抽象装饰器,并给具体构建扩展新的功能

/**
 * 具体装饰器 Concrete Decoretor
 * 实现抽象装饰器,并给具体构建添加扩展职责
 */
public class EggDecoretor extends BatterCakeDecoretor {
    public EggDecoretor(BatterCake batterCake) {
        super(batterCake);
    }

    @Override
    public String getMsg() {
        return super.getMsg()+",+1个鸡蛋";
    }

    @Override
    public int price() {
        return super.price()+1;
    }
}
/**
 * 具体装饰器 Concrete Decoretor
 * 实现抽象装饰器,并给具体构建添加扩展职责
 */
public class PancakesDecoretor extends BatterCakeDecoretor {
    public PancakesDecoretor(BatterCake batterCake) {
        super(batterCake);
    }

    @Override
    public String getMsg() {
        return super.getMsg()+",+1个火腿";
    }

    @Override
    public int price() {
        return super.price()+2;
    }
}

测试

    public static void main(String[] args) {
        System.out.println("=============测试一===========");
        // 创建一个煎饼
        BatterCake batterCake = new BaseBatterCake();
        System.out.println(batterCake.getMsg()+","+batterCake.price()+"块钱");
        // 给煎饼加一个鸡蛋
        BatterCakeDecoretor egg = new EggDecoretor(batterCake);
        System.out.println(egg.getMsg()+","+egg.price()+"块钱");
        // 给煎饼在加一根香肠
        BatterCakeDecoretor pancakes = new PancakesDecoretor(egg);
        System.out.println(pancakes.getMsg()+","+pancakes.price()+"块钱");
        // 给煎饼在加一个火腿
        BatterCakeDecoretor pancakes2 = new PancakesDecoretor(pancakes);
        System.out.println(pancakes2.getMsg()+","+pancakes2.price()+"块钱");

        System.out.println("=============测试2===========");
        // 给煎饼加两个鸡蛋一个火腿
        BatterCake cake = new PancakesDecoretor(new EggDecoretor(new EggDecoretor(new BaseBatterCake())));
        System.out.println(cake.getMsg()+","+cake.price()+"块钱");
    }
}

结果

=============测试一===========
煎饼,5块钱
煎饼,+1个鸡蛋,6块钱
煎饼,+1个鸡蛋,+1个火腿,8块钱
煎饼,+1个鸡蛋,+1个火腿,+1个火腿,10块钱
=============测试2===========
煎饼,+1个鸡蛋,+1个鸡蛋,+1个火腿,9块钱
装饰器模式实例应用

需求:用户列表默认使用的是 Id 排序,现在需求要使用 age 排序,过了几天项目经理又说,使用 name 排序...悲催了!为了不影响原有功能,这里使用装饰器模式
创建抽象构建

/**
 * 抽象构建 Component 数访问层
 */
public interface IUserService {

    public List<User> getUserList();
}

创建具体构建

/**
 * 具体构建 Concrete Component 业务逻辑层
 */
public class UserService implements IUserService{


    /**
     * 获取用户列表  默认根据用户 id 排序
     * @return
     */
    @Override
    public List<User> getUserList() {
        // 模拟查询到的数据
        List<User> userList = new ArrayList<User>(){};
        userList.add(new User(4, "张三",18));
        userList.add(new User(58, "李四",15));
        userList.add(new User(18, "王五",25));
        userList.add(new User(39, "张柳",48));
        userList.add(new User(14, "赵云",39));
        userList.add(new User(3, "蒙会",17));
        userList.sort(new Comparator<User>() {
            @Override
            public int compare(User o1, User o2) {
                return o1.getId() - o2.getId();
            }
        });
        return userList;
    }
}

创建抽象装饰类,继承抽象构建,持有具体构建的引用

/**
 * 抽象装饰器  Decoretor 继承抽象构建 持有具体构建的应用,规定子类必须实现的构造方法
 *
 */
public abstract class UserSortDecoretor implements IUserService{

    private IUserService userService;

    public UserSortDecoretor(IUserService userService){
        this.userService = userService;
    }

    @Override
    public List<User> getUserList() {
        return userService.getUserList();
    }
}

创建具体装饰器,实现抽象装饰类,为具体构建添加新的功能

/**
 * 具体装饰器Concrete Decoretor 实现抽象装饰,并给具体构建附加新的功能
 * 根据年龄排序
 */
public class UserSortByAgeDecoretor extends UserSortDecoretor{

    public UserSortByAgeDecoretor(IUserService userService) {
        super(userService);
    }

    @Override
    public List<User> getUserList() {
        List<User> userList = super.getUserList();
        userList.sort(new Comparator<User>() {
            @Override
            public int compare(User o1, User o2) {
                return o1.getAge()-o2.getAge();
            }
        });
        return userList;
    }
}
/**
 * 具体装饰器 Concrete Decoretor
 * 实现抽象装饰器,并给具体构建类添加新的功能
 */
public class UserSortByNameDecoretor extends UserSortDecoretor {

    public UserSortByNameDecoretor(IUserService userService) {
        super(userService);
    }

    @Override
    public List<User> getUserList() {
        List<User> userList = super.getUserList();
        userList.sort(new Comparator<User>() {
            @Override
            public int compare(User o1, User o2) {
                return o1.getName().compareTo(o2.getName());
            }
        });
        return userList;
    }
}

测试

    public static void main(String[] args) {
        IUserService idSort = new UserService();
        List<User> idSortList = idSort.getUserList();


        System.out.println("====================默认使用用户 id 排序==================");
        idSortList.forEach(user -> {
            System.out.println(user.getId()+","+user.getName()+","+user.getAge());
        });

        System.out.println("====================使用用户 age 排序==================");
        UserSortDecoretor ageSort = new UserSortByAgeDecoretor(idSort);
        List<User> ageSortList = ageSort.getUserList();
        ageSortList.forEach(user -> {
            System.out.println(user.getId()+","+user.getName()+","+user.getAge());
        });

        System.out.println("====================使用用户 name 排序==================");
        UserSortDecoretor nameSort = new UserSortByNameDecoretor(ageSort);
        List<User> nameSortList = nameSort.getUserList();
        nameSortList.forEach(user -> {
            System.out.println(user.getId()+","+user.getName()+","+user.getAge());
        });
    }

结果

====================默认使用用户 id 排序==================
3,蒙会,17
4,张三,18
14,赵云,39
18,王五,25
39,张柳,48
58,李四,15
====================使用用户 age 排序==================
58,李四,15
3,蒙会,17
4,张三,18
18,王五,25
14,赵云,39
39,张柳,48
====================使用用户 name 排序==================
4,张三,18
39,张柳,48
58,李四,15
18,王五,25
3,蒙会,17
14,赵云,39

相关文章

网友评论

      本文标题:装饰器模式(Decoretor Pattern)

      本文链接:https://www.haomeiwen.com/subject/iuwjvhtx.html