当前位置: 首页 > 科技观察

设计模式中的策略模式和状态模式

时间:2023-03-18 23:03:24 科技观察

使用场景状态模式:当对象的行为随着对象状态的变化而变化时,我们可以定义一个抽象状态,以便解耦多个判断条件,封装行为变化提供对象行为接口的类。具体的状态相关行为由其子类实现。策略模式:“策略”一词相当于一种算法。当真实系统需要动态指定算法并且可以相互替换时,可以抽象出算法的调用接口。具体的算法实现是通过具体的策略角色来实现的。根据RichterReplacement原则,凡是出现父类的地方,都可以用它的子类来代替,这就满足了我们的业务需求。比较虽然都抽象了父类的标准调用接口,具体行为由子类实现,环境对象也包含了父类的引用,但是两种模式的应用场景是完全不同的。比如:你去ATM取款,如果你的账户被冻结了,你就不能正常取款了。这里你的银行账户至少有两种状态:冻结和非冻结。你千万不要想着用策略模式来解决这样的业务方案。另一个例子是商场的折扣。有很多折扣策略。儿童产品30%折扣,老年产品50%折扣。ATM取款案例分析中设计的角色:取款人、账户、ATM机。在用例图中为了简单起见,分析取款用例。基本事件路径(1)取款人插入银行卡,输入密码;(2)选择取款操作,输入取款金额;(3)等待提现,提现。在此用例中,如果取款人账户被冻结,则会出现一个可选的事件路径,并且取款用例将终止。关键业务需求是用户取款,所以领域建模可以从识别取款和取款人这两个类开始。考虑到取款人不仅有取款的用例,我们将取款概括为一笔交易。ModelingUseCaseMaterializationWithdrawal:基本事件路径的物化。为了细化领域模型,引入边界对象ATMSystem作为负责与用户交互的控制器(与用户交互的ATM操作接口),Trade是负责处理用户交易的类。取款人插入银行卡并输入密码。ATMSystem负责将验证账户信息的消息传递给Trade交易类。Trade根据传入的账户密码验证用户是否存在,然后将处理结束的消息传递给ATMSystem边界对象反映给用户。分析模型中的某类提现设计-应用状态模式账户的状态分为冻结状态和激活状态。账户在激活状态下可以交易,冻结状态下不能交易。验证账户时,应返回当前账户的状态。如果账户被冻结,取款人进行取款操作时会直接返回错误信息。状态图如下:提现申请状态模式结构图:在账户验证阶段,如果账户处于冻结状态,则直接返回DeadAccount拒绝所有交易,否则返回ActiveAccount处理后续交易。示意图代码:这里为了简化实现,省略了ATMSystem的边界对象。用户账户信息抽象类///

///用户账户信息///publicabstractclassAccount{//////Account///privatestringaccount;///>///密码///privatestringpwd;publicabstractdecimalgetBalance(decimald);}冻结账户类//////冻结账户类///publicclassDeadAccount:Account{publicoverridedecimalgetBalance(decimal){return0;}}激活账户类//////激活账户类///publicclassActiveAccount:Account{publicoverridedecimalgetBalance(decimal){returnd;}}交易类//////负责用户交易处理的交易类///publicclassTrade{//////保存用户账户信息///privateAccountaccount;publicAccountVolidateLogin(Accounta){//querythedatabasetovalidatetheuserexists//ForExamplethis.account=newDeadAccount();returnthis.account;}//////撤回业务逻辑/////////<返回>publicdecimalGetBalance(decimal){returnthis.account.getBalance(d);}}用户类//////取款人///publicclassUser{//////用户账户信息///privateAccountaccount;//////交易处理类///privateTradetrade;publicUser(Accounta,Tradet){this.account=a;tthis.trade=t;}//////用户登录类///publicvoidLogin(){trade.VolidateLogin(account);}//////取款////////publicdecimalGetBalance(decimal){returntrade.GetBalance(d);}}客户端代码classClient{staticvoidMain(string[]args){//开始用户提现,默认是激活账户ActiveAccountaa=newActiveAccount();Tradet=newTrade();Useru=newUser(aa,t);//先登录,再提现u.Login();Console.WriteLine(u.GetBalance(100));Console.ReadLine();}}用户必须先登录(插入银行卡,输入密码,点击确定)后才能选择取款服务(选择取款).登录后返回的account对象是trade类的成员。办理取款业务时,直接向账户会员查询获取取款信息。如果账户是冻结账户,直接返回0。否则返回提取的值。商品打折案例案例描述:某超市为国庆促销,某类商品打折,如运动鞋20折,秋装10折等,张三去逛街买了一双运动鞋鞋子、一件秋装和一瓶洗发水。..,张三逛完回家,想着自己今天一共“赚”了多少钱?案例分析:商家可能有多种商品折扣策略。这里使用strategy模式封装了商品折扣策略,这样以后可以在不修改原有代码的情况下对折扣策略进行扩展,具有很好的灵活性。模式中涉及的角色:抽象策略角色:通常由接口或抽象实现;具体策略作用:包装相关算法和行为;环境角色:包含对抽象策略角色的引用,最终由用户使用。商品折扣案例设计图顾客购物涉及的角色包括:购物车、商品、收银机、抽象策略角色和具体策略角色。购物车:是放置商品的容器,提供增删操作;goods:商品实体,具有类型、商品名称、价格等属性;收银机:负责收款,主要计算客户购买的所有商品的价格和折扣总额;抽象策略作用:提供折扣策略接口。具体策略作用:实现具体的折扣算法。商品折扣码://////具体商品类别///publicclassgoods{//////商品类型///publicstringType{set;get;}//////产品名称///publicstringName{get;set;}//////产品价格///publicdecimalPrice{get;set;}}抽象策略角色//////抽象策略接口///publicinterfaceIDiscountStrategy{decimalGetDiscount(goodsg);}具体策略角色//////秋装打折策略///publicclassAutumnDressDiscountStrategy:IDiscountStrategy{#regionIDiscountStrategyMemberspublicdecimalGetDiscount(goodsg){return(decimal)0.9*g.Price;}#endregion}//////运动鞋打折攻略///publicclassSportShoes:DiscountStrategyIDiscountStrategy{#regionIDiscountStrategyMemberspublicdecimalGetDiscount(goodsg){returng.Price*(decimal)0.8;}#endregion}购物车//////购物车类负责产品维护///publicclassShoppingCar{privateListgoodsList=newList();//////将商品加入购物车//////publicvoidAddGoods(goodsg){goodsList.Add(g);}//////从购物车中移除商品//////publicvoidRemoveGoods(goodsg){goodsList.Remove(g);}publicListGoodsList{get{returngoodsList;}}}收银员角色//////CashierDesk///publicclassCashierDesk{//////购物车///privateShoppingCarshoppingCar;//////策略字典///privateDictionarystrategies;publicCashierDesk(ShoppingCarsc,Dictionarys){this.shoppingCar=sc;this.strategies=s;}//////获取所有商品的价格//////publicdecimalGetTotalPrice(){returnshoppingCar.GoodsList.Sum(p=>p.Price);}//////获取所有商品的总折扣//////publicdecimalGetTotalDiscount(){decimalsum=0;IDiscountStrategyidiscountStrategy;foreach(goodsginshoppingCar.GoodsList){idiscountStrategy=strategies.SingleOrDefault(p=>p.Key==g.Type).Value;if(idiscountStrategy!=null){sum+=idiscountStrategy.GetDiscount(g);}}returnsum;}}客户端代码classClient{staticvoidMain(string[]args){ShoppingCarsc=newShoppingCar();DictionarydiscountD=newDictionary();//添加商品到购物车sc.AddGoods(newgoods{Name="耐克鞋",Price=100,Type="运动鞋"});sc.AddGoods(newgoods{Name="秋装",Price=200,Type="秋装"});sc.AddGoods(newgoods{Name="Apple",Price=300,Type="Fruit"});//配置折扣策略discountD.Add("运动鞋",newSportShoesDiscountStrategy());discountD.Add("秋装",newAutumnDressDiscountStrategy());CashierDeskcd=newCashierDesk(sc,discountD);//获取所有商品的总价Console.WriteLine(cd.GetTotalPrice());//获取所有商品的折扣价Console.WriteLine(cd.GetTotalDiscount());Console.ReadLine();}}策略模式的优点缺点:优点是封装了算法的不稳定性,以后容易扩展业务策略。缺点是每一个策略对应一个特定的策略角色类,会增加系统需要维护的类的数量。原文链接:http://www.cnblogs.com/ejiyuan/archive/2012/06/28/2567905.html【编者推荐】Java设计模式:适配器模式趣味浅析Java23设计模式函数式思维:函数设计模式部分3结合设计模式谈如何设计类结合设计模式谈类设计