java与模式孙悟空_由孙悟空的七十二变看Java设计模式:装饰者模式
應用場景
京東、天貓雙十一,情人節商品大促銷,各種商品有不同的促銷活動
滿減:滿200減50
每滿減:每滿100減10
打折:買兩件8折,三件7折
數量減:滿三件減去最低價的一件
假設現在顧客買了兩件衣服先是打了8折,然后又滿200減了50,促銷活動多重疊加了,該如何靈活實現訂單金額計算?
代碼示例
PromotionAlgorithm接口,計算訂單金額:
public interface PromotionAlgorithm{
Order promotionAlgorithm(Order order);
}
復制代碼
實現類PromotionAlgorithm1、PromotionAlgorithm2:
public class PromotionAlgorithm1 implements PromotionAlgorithm{
@Override
public Order promotionAlgorithm(Order order){
System.out.println("打8折");
order.setPrice(order.getPrice() * 0.8);
return order;
}
}
復制代碼
public class PromotionAlgorithm2 implements PromotionAlgorithm{
@Override
public Order promotionAlgorithm(Order order){
System.out.println("滿200減了50");
order.setPrice(order.getPrice() - 50);
return order;
}
}
復制代碼
OrderService類:
public class OrderService{
public Order getOrderPrices(Order order, String... promotion){
for (String s : promotion) {
if (s.equals("promotion-1")) {
new PromotionAlgorithm1().promotionAlgorithm(order);
} else if (s.equals("promotion-2")) {
new PromotionAlgorithm2().promotionAlgorithm(order);
}
}
return order;
}
}
復制代碼
測試類:
public class Test{
public static void main(String[] args){
OrderService service = new OrderService();
Order order = new Order();
order.setPrice(1000.0);
String[] array = {"promotion-1", "promotion-2"};
Order result = service.getOrderPrices(order, array);
System.out.println("最終我花了:" + result.getPrice());
}
}
復制代碼
現在思考一下,當需要對一個類的多個方法進行增強時,使用者會隨意使用被增強方法時,上面的for循環還靈活嗎
改進代碼
定義一個接口OrderComponent:
public interface OrderComponent{
/** 促銷方式 */
String getPromotion();
/** 價格 */
Double getPrice();
}
復制代碼
OrderConcreteComponent類:需要進行計算的類
public class OrderConcreteComponent implements OrderComponent{
@Override
public String getPromotion(){
return "我買了三件衣服,衣服總共1000元,";
}
@Override
public Double getPrice(){
return 1000.0;
}
}
復制代碼
OrderDecorator類:有一個屬性,是上面的接口OrderComponent,實現了OrderComponent接口
public class OrderDecorator implements OrderComponent{
public OrderComponent component;
public OrderDecorator(OrderComponent component){
this.component = component;
}
@Override
public String getPromotion(){
return this.component.getPromotion();
}
@Override
public Double getPrice(){
return this.component.getPrice();
}
}
復制代碼
OrderDecoratorA類:打折類
public class OrderDecoratorA extends OrderDecorator{
public OrderDecoratorA(OrderComponent component){
super(component);
}
@Override
public String getPromotion(){
return this.component.getPromotion() + "衣服打了8折,";
}
@Override
public Double getPrice(){
return this.component.getPrice() * 0.8;
}
}
復制代碼
OrderDecoratorB類:滿減類
public class OrderDecoratorB extends OrderDecorator{
public OrderDecoratorB(OrderComponent component){
super(component);
}
@Override
public String getPromotion(){
return this.component.getPromotion() + "又滿200減了50。";
}
@Override
public Double getPrice(){
return this.component.getPrice() - 50;
}
}
復制代碼
測試類:
public class Test{
public static void main(String[] args){
OrderComponent component = new OrderConcreteComponent();
OrderComponent c = new OrderDecorator(component);
OrderComponent d = new OrderDecoratorA(c);
OrderComponent e = new OrderDecoratorB(d);
System.out.println(e.getPromotion());
System.out.println("最終我花了:" + e.getPrice());
}
}
復制代碼
上面的改進代碼,就是裝飾者模式的基本運用
裝飾者模式
定義
以裝飾的方式,動態地將責任附加到對象上,同時又不改變其結構
意圖
動態地給一個對象添加一些額外的職責。就增加功能來說,裝飾者模式相比生成子類更為靈活
主要解決問題
一般的,我們為了擴展一個類經常使用繼承方式實現,由于繼承為類引入靜態特征,并且隨著擴展功能的增多,子類會很膨脹
何時使用
在不想增加很多子類的情況下擴展類
優缺點
優點:
不改變具體類代碼,動態疊加增強行為功能
若要擴展功能,裝飾者提供了比繼承更有彈性的替代方案
裝飾類和被裝飾類可以獨立發展,不會相互耦合
缺點:
多層裝飾比較復雜
類圖:
涉及到的角色:
抽象構建(Component)角色:給出一個抽象接口,來規范準備接收附加責任的對象
具體構建(ConcreteComponent)角色:定義一個將要接收附加責任的類,即被裝飾者
裝飾(Decorator)角色:持有一個構建(Component)對象的實例,并定義一個與抽象接口一致的接口
具體裝飾(ConcreteDecorator)角色:即上圖中的DecoratorA、DecoratorB,負責給構建對象貼上附加的責任,即具體的功能增強行為在這個角色里面
Component類:
public interface Component{
void sampleOperation();
}
復制代碼
ConcreteComponent類:
public class ConcreteComponent implements Component{
@Override
public void sampleOperation(){
//do something
}
}
復制代碼
Decorator類:
public class Decorator implements Component{
private Component component;
public Decorator(Component component){
this.component = component;
}
@Override
public void sampleOperation(){
this.component.sampleOperation();
}
}
復制代碼
ConcreteDecorator類:
public class ConcreteDecorator extends Decorator{
public ConcreteDecorator(Component component){
super(component);
}
@Override
public void sampleOperation(){
super.sampleOperation();
}
}
復制代碼
裝飾者模式常常也被稱為包裹模式,就是因為每一個具體的裝飾類都將下一個具體裝飾類或者具體構建類包裹起來
假設有2個具體裝飾類Decorator1、Decorator2,還有一個具體構建類ConcreteComponent:
是的沒錯,就是像套娃一樣,一層包裹一層
孫悟空的七十二變
大家都知道,孫悟空有七十二般變化,每一種變化都會給他帶來一種附加的本領,變成魚可以在水中游,變成鳥可以在空中飛,但是無論怎么樣的變化,在二郎神眼中,還是一只猴子
齊天大圣類:擁有七十二般變化
public interface MonkeyKing{
/** 七十二變 */
String change();
}
復制代碼
大圣本尊類:
public class ConcreteMonkey implements MonkeyKing{
@Override
public String change(){
return "我是齊天大圣本尊!";
}
}
復制代碼
大圣化身類:
public class DecoratorMonkeyChange implements MonkeyKing{
public MonkeyKing king;
public DecoratorMonkeyChange(MonkeyKing king){
this.king = king;
}
@Override
public String change(){
return this.king.change();
}
}
復制代碼
大圣具體化身類:
public class DecoratorMonkeyChange1 extends DecoratorMonkeyChange{
public DecoratorMonkeyChange1(MonkeyKing king){
super(king);
}
@Override
public String change(){
return this.king.change() + "變成了魚!";
}
}
復制代碼
public class DecoratorMonkeyChange2 extends DecoratorMonkeyChange{
public DecoratorMonkeyChange2(MonkeyKing king){
super(king);
}
@Override
public String change(){
return this.king.change() + "變成了鳥!";
}
}
復制代碼
測試類:
public class TestMonkey{
public static void main(String[] args){
MonkeyKing king = new ConcreteMonkey();
MonkeyKing a = new DecoratorMonkeyChange(king);
MonkeyKing b = new DecoratorMonkeyChange1(a);
MonkeyKing c = new DecoratorMonkeyChange2(b);
System.out.println(c.change());
}
}
復制代碼
類圖:
總結
以上是生活随笔為你收集整理的java与模式孙悟空_由孙悟空的七十二变看Java设计模式:装饰者模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 「区块链+数字身份」:DID 身份认证的
- 下一篇: win7设置wifi热点_Windows