Android中装饰者模式
2017-11-06 14:30
218 查看
设计模式系列:
0. Android开发常用设计模式;
1. Android中单例模式;
2. Android中建造者(builder)模式;
3. Android中观察者模式;
4. Android中原型模式;
5. Android中策略模式;
6. Android中工厂模式;
7. Android中代理模式;
8. Android中装饰者模式;
9. Android中适配器模式;
三毛:“小白,你用过’饿了吗’app不”
小白:嘿嘿,向我这样与时俱进的年轻人肯定用过吖
三毛:“像下面的就是‘饿了么’某店的水果拼盘商品,见过吧”
小白:嗯嗯
(A)西瓜+哈密瓜
(B)西瓜+葡萄
(C)哈密瓜+葡萄
(D)西瓜+哈密瓜+葡萄
顾客买了水果拼盘后就输出它的名字和价格,你来模拟下”
方法1
方法2
三毛:“小白,可以吖,鬼点子挺多的嘛”
小白:还行,还行
小白:
三毛:”不相信的话,那我来分析分析给你听,我们是讲道理的嘛”
小白:好吧,毛毛哥你分析分析,我听听看
三毛:“方法1,白,假设我多加5种水果,套餐就达到26种,有2种盒子,那你不得写26*2个套餐类喔,而且我说的只是5种,如果更加多的话,岂不是累死你了”
小白:
有点道理
三毛:”方法2,这个写法确实没有方法1那种问题了,但是,如果功能扩展的时候你是不是得在NormalBoxPackageImpl或VipBoxPackageImpl类里做修改,比如加多个火龙果,你就加多个火龙果方法,套餐中有火龙果的话,你就相当于改变了价格和套餐名字(你要计算价格…),很明显违反了设计模式六大原则中的开闭原则的闭,也就是,新增功能的时候,不能去修改原有的代码”
小白:我觉得第二种方法挺好的吖,简单粗暴,违反就违反呗
三毛:”我只是和你说你那样写存在那样的问题,并不是说不能用,其实看场景和需求考虑就好”
小白:我就是这样想滴,毛毛哥哥
三毛:”小白,如果装饰者模式能像你上面方法2一样,但是又不违反设计模式规则,你觉得怎么样”
小白:
快给我讲讲,毛毛哥
三毛:”睁大眼睛看好了,使用装饰者模式完成上面需求的正确姿势”
小白:使用装饰者模式后,不管套餐有几百个,我们只需要增加对应的水果,然后自己随心所欲组合就好了,而且相互独立不影响
三毛:”嗯,装饰者模式就像穿衣服,一层套一层,先穿什么,在穿什么都可以,只要是衣服(实现同一接口)类型”
小白:呐,毛毛哥,装饰者模式一定要按上面的标准写四个东西嘛
三毛:”我的白,你不要误解喔,上面只是标准做法,实际当中你要根据业务来做,虽然模式是这样,但是只要你代码写得好就行,管它怎样讷,比如上面的普通盒子和Vip盒子类我可以不按上面那样写,可以像下面这样写”
小白:”这样写比标准写法少了个抽象类啊,这样不会有什么影响嘛”
三毛;”多个套餐抽象类看起来比较清晰明了啊,如果非要说有影响的话,就是当你扩展业务时,比如在使用盒子装水果套餐前询问用户是否使用本店优惠券,你还不是得在多加一个接口或抽象类?不过我认为怎么写没关系,模式只是提供你一些思路,写代码考虑好问题就没毛病”
小白:
2、符合设计原则中的开闭原则;
3、比某些正常写法少了很多类和工作;
4、随心所欲按你的顺序组合,灵活多变。
0. Android开发常用设计模式;
1. Android中单例模式;
2. Android中建造者(builder)模式;
3. Android中观察者模式;
4. Android中原型模式;
5. Android中策略模式;
6. Android中工厂模式;
7. Android中代理模式;
8. Android中装饰者模式;
9. Android中适配器模式;
三毛:“小白,你用过’饿了吗’app不”
小白:嘿嘿,向我这样与时俱进的年轻人肯定用过吖
三毛:“像下面的就是‘饿了么’某店的水果拼盘商品,见过吧”
小白:嗯嗯
一、常见需求场景
三毛:“假设现在某店分普通和VIP两种盒子装水果拼盘,现在只有下面4种水果套餐拼盘:(A)西瓜+哈密瓜
(B)西瓜+葡萄
(C)哈密瓜+葡萄
(D)西瓜+哈密瓜+葡萄
顾客买了水果拼盘后就输出它的名字和价格,你来模拟下”
二、基本解决方法
小白:毛毛哥,我想到下面2种写法方法1
//--------------------------水果类--------------------------// //来个水果接口 public interface IFruit { String getFruitName(); double getFruitPrice(); } //西瓜 public class XiGua implements IFruit { @Override public String getFruitName() { return "西瓜"; } @Override public double getFruitPrice() { return 2.00; } } //...其他哈密瓜,葡萄一样,这里就不写了 //--------------------------水果套餐类--------------------------// //来个盒子接口 public interface IBox { void boxType();//盒子类型 String getPackageName();//获取套餐名字 double getPackagePrice();//获取套餐价格 } //普通盒子装的水果拼盘套餐A public class NormalBoxA implements IBox { private XiGua mXiGua; private HaMiGua mHaMiGua; public NormalBoxA() { mXiGua = new XiGua(); mHaMiGua = new HaMiGua(); } @Override public void boxType() { System.out.println("普通盒子装的"); } @Override public String getPackageName() { boxType(); return mXiGua.getFruitName()+"+"+mHaMiGua.getFruitName(); } @Override public double getPackagePrice() { return mXiGua.getFruitPrice()+mHaMiGua.getFruitPrice()+0.5; } } //Vip盒子装的水果拼盘套餐A(和普通盒子没啥区别,价格贵了点) public class VipBoxA implements IBox { private XiGua mXiGua; private HaMiGua mHaMiGua; public VipBoxA() { mXiGua = new XiGua(); mHaMiGua = new HaMiGua(); } @Override public void boxType() { System.out.println("Vip盒子装的"); } @Override public String getPackageName() { boxType(); return mXiGua.getFruitName()+"+"+mHaMiGua.getFruitName(); } @Override public double getPackagePrice() { return mXiGua.getFruitPrice()+mHaMiGua.getFruitPrice(); } } //...其他B、C、D套餐也是一样,这里就不重复了 //使用 NormalBoxA normalBoxA = new NormalBoxA(); VipBoxA vipBoxA = new VipBoxA(); System.out.println(normalBoxA.getPackageName()+":"+normalBoxA.getPackagePrice()); System.out.println(vipBoxA.getPackageName()+":"+vipBoxA.getPackagePrice()); //其他套餐使用也一样...
方法2
//来个枚举或常量类(随便啦) public enum FruitType { XiGua(2.00,"西瓜"),HaMiGua(6.00,"哈密瓜"),PuTao(8.50,"葡萄"); private double price; private String name; FruitType(double price, String name) { this.price = price; this.name = name; } public double getPrice() { return price; } public String getName() { return name; } } //------------------------------套餐类------------------------------// //在来个套餐接口类 public interface IPackage { void boxType();//盒子类型 String getPackageName();//得到套餐名字 double getPackagePrice();//得到套餐价格 } //来个普通盒子装的套餐实现类 public class NormalBoxPackageImpl implements IPackage { private double mPrice; private String mFruitPackageName = ""; public void addXiGua() { mPrice += FruitType.XiGua.getPrice(); mFruitPackageName += FruitType.XiGua.getName() + "+"; } public void addHaMiGua() { mPrice += FruitType.HaMiGua.getPrice(); mFruitPackageName += FruitType.HaMiGua.getName() + "+"; } public void addPuTao() { mPrice += FruitType.PuTao.getPrice(); mFruitPackageName += FruitType.PuTao.getName() + "+"; } @Override public void boxType() { System.out.println("普通盒子装的"); } @Override public String getPackageName() { boxType(); return mFruitPackageName.isEmpty() ? "" : mFruitPackageName.substring(0, mFruitPackageName.length() - 1); } @Override public double getPackagePrice() { return mPrice; } } //另外VipBoxPackageImpl类省略,vip盒子装的和普通盒子装的没多少区别,只是套餐价格贵了点... //使用 NormalBoxPackageImpl normalBoxPackage= new NormalBoxPackageImpl(); normalBoxPackage.addHaMiGua();//要什么水果套餐,自己拼就OK了 System.out.println(normalBoxPackage.getPackageName()+":"+normalBoxPackage.getPackagePrice());
三毛:“小白,可以吖,鬼点子挺多的嘛”
小白:还行,还行
三、基本解决方法存在的问题
三毛:“鬼点子多是多,但是上面的两种方法都存在相应的问题喔”小白:
三毛:”不相信的话,那我来分析分析给你听,我们是讲道理的嘛”
小白:好吧,毛毛哥你分析分析,我听听看
三毛:“方法1,白,假设我多加5种水果,套餐就达到26种,有2种盒子,那你不得写26*2个套餐类喔,而且我说的只是5种,如果更加多的话,岂不是累死你了”
小白:
有点道理
三毛:”方法2,这个写法确实没有方法1那种问题了,但是,如果功能扩展的时候你是不是得在NormalBoxPackageImpl或VipBoxPackageImpl类里做修改,比如加多个火龙果,你就加多个火龙果方法,套餐中有火龙果的话,你就相当于改变了价格和套餐名字(你要计算价格…),很明显违反了设计模式六大原则中的开闭原则的闭,也就是,新增功能的时候,不能去修改原有的代码”
小白:我觉得第二种方法挺好的吖,简单粗暴,违反就违反呗
三毛:”我只是和你说你那样写存在那样的问题,并不是说不能用,其实看场景和需求考虑就好”
小白:我就是这样想滴,毛毛哥哥
三毛:”小白,如果装饰者模式能像你上面方法2一样,但是又不违反设计模式规则,你觉得怎么样”
小白:
快给我讲讲,毛毛哥
四、装饰者模式写法
装饰者模式定义:动态给一个对象添加一些额外的职责。装饰着模式相比用生成子类方式达到功能的扩展显得更加灵活。三毛:”睁大眼睛看好了,使用装饰者模式完成上面需求的正确姿势”
//装饰者模式标准写法,分为4个部分 -->(1)接口;(2)实现接口;(3)抽象类;(4)实现抽象类。 //先来个接口 public interface IGoods { String getName();//获取商品名字 double getPrice();//获取商品价格 } //实现商品接口的西瓜 public class XiGua implements IGoods { private IGoods mIGoods; public XiGua(IGoods mIGoods) { this.mIGoods = mIGoods; } @Override public String getName() { return null == mIGoods ?"西瓜":mIGoods.getName() + "+西瓜"; } @Override public double getPrice() { return null == mIGoods ?2.00:mIGoods.getPrice() + 2.00; } } //哈密瓜、普通...和上面一样,代码省略... //来个套餐抽象类 public abstract class AbstractPackage implements IGoods { public IGoods mIGoods; //你也可以在这里加一些商品接口没有的抽象方法,实现扩展... public AbstractPackage(IGoods mIGoods) { this.mIGoods = mIGoods; } //获取套餐(商品)名字 public String getPackageName() { return mIGoods.getName(); } //获取套餐(商品)价格 public double getPackagePrice() { return mIGoods.getPrice(); } } //实现抽象类 -->普通盒子装的水果套餐类 public class NormalBox extends AbstractPackage { NormalBox(IGoods mIGoods) { super(mIGoods); } @Override public String getName() { return "普通盒子装的:" + super.getPackageName(); } @Override public double getPrice() { return 0.5 + super.getPackagePrice(); } } //实现抽象类 -->Vip盒子装的水果套餐类 public class VipBox extends AbstractPackage { public VipBox(IGoods mIGoods) { super(mIGoods); } @Override public String getName() { return "Vip盒子装的:" + super.getPackageName(); } @Override public double getPrice() { return 1.5 + super.getPackagePrice(); } } //使用 XiGua xiGua = new XiGua(null); HaMiGua haMiGua = new HaMiGua(xiGua);//随意组装你想要的水果(拼盘) NormalBox normalBox = new NormalBox(haMiGua);//放到你想要的盒子里 System.out.println(normalBox.getName() + ":" + normalBox.getPrice());
小白:使用装饰者模式后,不管套餐有几百个,我们只需要增加对应的水果,然后自己随心所欲组合就好了,而且相互独立不影响
三毛:”嗯,装饰者模式就像穿衣服,一层套一层,先穿什么,在穿什么都可以,只要是衣服(实现同一接口)类型”
小白:呐,毛毛哥,装饰者模式一定要按上面的标准写四个东西嘛
三毛:”我的白,你不要误解喔,上面只是标准做法,实际当中你要根据业务来做,虽然模式是这样,但是只要你代码写得好就行,管它怎样讷,比如上面的普通盒子和Vip盒子类我可以不按上面那样写,可以像下面这样写”
//不实现抽象类了,改成实现商品接口 public class NormalBox implements IGoods { public IGoods mIGoods; public NormalBox(IGoods mIGoods) { this.mIGoods = mIGoods; } @Override public String getName() { return "普通盒子装的:" + mIGoods.getName(); } @Override public double getPrice() { return 0.5 + mIGoods.getPrice(); } } //Vip盒子实现类也可以换成这样写.... //使用还是没变化...
小白:”这样写比标准写法少了个抽象类啊,这样不会有什么影响嘛”
三毛;”多个套餐抽象类看起来比较清晰明了啊,如果非要说有影响的话,就是当你扩展业务时,比如在使用盒子装水果套餐前询问用户是否使用本店优惠券,你还不是得在多加一个接口或抽象类?不过我认为怎么写没关系,模式只是提供你一些思路,写代码考虑好问题就没毛病”
小白:
五、装饰者模式和普通写法区别
1、结构清晰,耦合度更低,扩展性更强;2、符合设计原则中的开闭原则;
3、比某些正常写法少了很多类和工作;
4、随心所欲按你的顺序组合,灵活多变。
相关文章推荐
- Android装饰者模式学习笔记(1)
- Android装饰者模式学习笔记(2)
- Android设计模式之一个例子让你彻底明白装饰者模式(Decorator Pattern)
- Android与设计模式——装饰者(Decorator)模式
- 设计模式-装饰者模式(Decorator)理解和在Android中的应用
- java4Android(15)处理流的使用示例、装饰者设计模式、节点流和处理流的关系
- Android 设计模式之装饰者模式
- Android设计模式之中的一个个样例让你彻底明确装饰者模式(Decorator Pattern)
- android开发 装饰者模式
- Android装饰者模式介绍(结合源码分析)
- Android小白的探索:2D绘图之Android简易版Microsoft Visio学习之路 三、装饰者模式
- Android 设计模式:(三)装饰者模式 —— 装饰对象
- 生拉硬套设计模式(一),关于装饰者模式在Android项目中的运用。
- Android开发中无处不在的设计模式——装饰者模式
- Android设计模式之装饰者模式(Decorator Pattern)
- Android 设计模式:(三)装饰者模式 —— 装饰对象
- 装饰者模式在Android上的应用 之 Context
- Android 设计模式:(三)装饰者模式 —— 装饰对象
- android 设计模式 ——装饰者模式(给你的代码穿上漂亮的衣服 )
- Android 装饰者模式