网站流量外流,企业网站设计软件,网站怎么挖掘关键词,一份简短的项目计划书前言 作为一名资深CV工程师#xff0c;学会为自己减少工作量乃重中之重。但只是一味地CV#xff0c;只会因为劣质代码而让自己的工作量加倍#xff0c;为了将来不被繁重的维护工作而打扰自己的休息日#xff0c;为了更好的节能#xff0c;学习设计模式#xff0c;刻不容缓… 前言 作为一名资深CV工程师学会为自己减少工作量乃重中之重。但只是一味地CV只会因为劣质代码而让自己的工作量加倍为了将来不被繁重的维护工作而打扰自己的休息日为了更好的节能学习设计模式刻不容缓。 模版方法
概念
生活中我们总是离不开各种模版的存在作文、文章、简历的模版。正是因为这些模板的存在我们工作的效率才大大提高而设计模式的中模版方法正是与现实生活中的模版如出一辙。
现实中的模版一般有两类一类为只有大体框架的而另一类为全部都填写完的只需要修改你想要的部分即可。我们在设计模版方法的时候可以设计一个骨架作为调用流程而具体的功能/算法则留给派生类来实现。或者将那些会变化的代码逻辑封装起来如果有需要再留给派生类更改。
定义
模版方法指的是为算法定义一个大体运行框架而将那些会变化的代码封装起来而留给派生类实现的一种设计模式。
代码实现
以冲泡饮料为例冲泡的步骤基本都不会改变只有一部分细节会有变化正好可以使用模版方法进行设计封装。 #mermaid-svg-rA49nIUBMjSJ15pU {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-rA49nIUBMjSJ15pU .error-icon{fill:#552222;}#mermaid-svg-rA49nIUBMjSJ15pU .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-rA49nIUBMjSJ15pU .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-rA49nIUBMjSJ15pU .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-rA49nIUBMjSJ15pU .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-rA49nIUBMjSJ15pU .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-rA49nIUBMjSJ15pU .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-rA49nIUBMjSJ15pU .marker{fill:#333333;stroke:#333333;}#mermaid-svg-rA49nIUBMjSJ15pU .marker.cross{stroke:#333333;}#mermaid-svg-rA49nIUBMjSJ15pU svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-rA49nIUBMjSJ15pU g.classGroup text{fill:#9370DB;fill:#131300;stroke:none;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-rA49nIUBMjSJ15pU g.classGroup text .title{font-weight:bolder;}#mermaid-svg-rA49nIUBMjSJ15pU .nodeLabel,#mermaid-svg-rA49nIUBMjSJ15pU .edgeLabel{color:#131300;}#mermaid-svg-rA49nIUBMjSJ15pU .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-rA49nIUBMjSJ15pU .label text{fill:#131300;}#mermaid-svg-rA49nIUBMjSJ15pU .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-rA49nIUBMjSJ15pU .classTitle{font-weight:bolder;}#mermaid-svg-rA49nIUBMjSJ15pU .node rect,#mermaid-svg-rA49nIUBMjSJ15pU .node circle,#mermaid-svg-rA49nIUBMjSJ15pU .node ellipse,#mermaid-svg-rA49nIUBMjSJ15pU .node polygon,#mermaid-svg-rA49nIUBMjSJ15pU .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-rA49nIUBMjSJ15pU .divider{stroke:#9370DB;stroke:1;}#mermaid-svg-rA49nIUBMjSJ15pU g.clickable{cursor:pointer;}#mermaid-svg-rA49nIUBMjSJ15pU g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-rA49nIUBMjSJ15pU g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-rA49nIUBMjSJ15pU .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-rA49nIUBMjSJ15pU .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-rA49nIUBMjSJ15pU .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-rA49nIUBMjSJ15pU .dashed-line{stroke-dasharray:3;}#mermaid-svg-rA49nIUBMjSJ15pU #compositionStart,#mermaid-svg-rA49nIUBMjSJ15pU .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-rA49nIUBMjSJ15pU #compositionEnd,#mermaid-svg-rA49nIUBMjSJ15pU .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-rA49nIUBMjSJ15pU #dependencyStart,#mermaid-svg-rA49nIUBMjSJ15pU .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-rA49nIUBMjSJ15pU #dependencyStart,#mermaid-svg-rA49nIUBMjSJ15pU .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-rA49nIUBMjSJ15pU #extensionStart,#mermaid-svg-rA49nIUBMjSJ15pU .extension{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-rA49nIUBMjSJ15pU #extensionEnd,#mermaid-svg-rA49nIUBMjSJ15pU .extension{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-rA49nIUBMjSJ15pU #aggregationStart,#mermaid-svg-rA49nIUBMjSJ15pU .aggregation{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-rA49nIUBMjSJ15pU #aggregationEnd,#mermaid-svg-rA49nIUBMjSJ15pU .aggregation{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-rA49nIUBMjSJ15pU .edgeTerminals{font-size:11px;}#mermaid-svg-rA49nIUBMjSJ15pU :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Beverage void PrepareRecipe() ~Beverage() #void BoilWater() #void PourInCup() #void Brew() #void AddCondiments() Coffee #void Brew() #void AddCondiments() Tea #void Brew() #void AddCondiments() 代码实例
class Beverage
{
public:void PrepareRecipe(){ // 代码运行的大体框架BoilWater();PourInCup();Brew();AddCondiments();}virtual ~Beverage() default;
protected:// 具体实现可留给子类实现virtual void BoilWater(){std::cout Boiling water std::endl;}virtual void PourInCup(){std::cout Pouring into cup std::endl;}virtual void Brew() 0;virtual void AddCondiments() 0;
};class Coffee : public Beverage
{
protected:void Brew() override { std::cout Brewing coffee std::endl; }void AddCondiments() override { std::cout Adding sugar and milk std::endl; }
};class Tea : public Beverage
{
protected:void Brew() override { std::cout Brewing tea std::endl; }void AddCondiments() override { std::cout Adding lemon std::endl; }
};钩子方法
钩子方法是模版方法的一种变体它在框架中定义一个判断方法钩子让子类来决定其代码逻辑减少了减少了外部的干预提高了代码的灵活度与拓展性。
继续用上方的饮料代码来举例就是不是所有都饮料中都需要添加调味剂/配料此时可以由子类决定其算法逻辑。
代码实例
class Beverage
{
public:void PrepareRecipe(){ // 代码运行的大体框架BoilWater();PourInCup();Brew();if (NeedCondiments()) AddCondiments();}virtual ~Beverage() default;
protected:// 钩子方法virtual bool NeedCondiments() { return false; }// 具体实现可留给子类实现virtual void BoilWater(){std::cout Boiling water std::endl;}virtual void PourInCup(){std::cout Pouring into cup std::endl;}virtual void Brew() {std::cout Brew some drink; };virtual void AddCondiments() { std::cout Adding some condiments; }
};class Coffee : public Beverage
{
protected:bool NeedCondiments() override { return true; }void Brew() override { std::cout Brewing coffee std::endl; }void AddCondiments() override { std::cout Adding sugar and milk std::endl; }
};策略模式
概念
策略模式指的是将算法封装起来(成员变量/接口)使其能够根据不同情况而更换。策略模式与模版方法都需要将其算法/实现封装起来初认可能会将其混淆但只要认清模版方法是将实现延迟到子类实现而策略模式是变化封装成类(接口/委托)就不会混淆了。
这里使用支付系统作为例子随着互联网的发展我们的支付方式越发变得丰富如果每增加一个支付方式支付系统都要重写代码的话那么想必程序员都再也不用担心失业了。这种情况下使用策略模式将支付手段封装起来那么就正好符合OO原则中的开闭原则系统的维护性也更好。 #mermaid-svg-o5eum7dlLbCp7b7t {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-o5eum7dlLbCp7b7t .error-icon{fill:#552222;}#mermaid-svg-o5eum7dlLbCp7b7t .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-o5eum7dlLbCp7b7t .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-o5eum7dlLbCp7b7t .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-o5eum7dlLbCp7b7t .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-o5eum7dlLbCp7b7t .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-o5eum7dlLbCp7b7t .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-o5eum7dlLbCp7b7t .marker{fill:#333333;stroke:#333333;}#mermaid-svg-o5eum7dlLbCp7b7t .marker.cross{stroke:#333333;}#mermaid-svg-o5eum7dlLbCp7b7t svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-o5eum7dlLbCp7b7t g.classGroup text{fill:#9370DB;fill:#131300;stroke:none;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-o5eum7dlLbCp7b7t g.classGroup text .title{font-weight:bolder;}#mermaid-svg-o5eum7dlLbCp7b7t .nodeLabel,#mermaid-svg-o5eum7dlLbCp7b7t .edgeLabel{color:#131300;}#mermaid-svg-o5eum7dlLbCp7b7t .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-o5eum7dlLbCp7b7t .label text{fill:#131300;}#mermaid-svg-o5eum7dlLbCp7b7t .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-o5eum7dlLbCp7b7t .classTitle{font-weight:bolder;}#mermaid-svg-o5eum7dlLbCp7b7t .node rect,#mermaid-svg-o5eum7dlLbCp7b7t .node circle,#mermaid-svg-o5eum7dlLbCp7b7t .node ellipse,#mermaid-svg-o5eum7dlLbCp7b7t .node polygon,#mermaid-svg-o5eum7dlLbCp7b7t .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-o5eum7dlLbCp7b7t .divider{stroke:#9370DB;stroke:1;}#mermaid-svg-o5eum7dlLbCp7b7t g.clickable{cursor:pointer;}#mermaid-svg-o5eum7dlLbCp7b7t g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-o5eum7dlLbCp7b7t g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-o5eum7dlLbCp7b7t .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-o5eum7dlLbCp7b7t .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-o5eum7dlLbCp7b7t .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-o5eum7dlLbCp7b7t .dashed-line{stroke-dasharray:3;}#mermaid-svg-o5eum7dlLbCp7b7t #compositionStart,#mermaid-svg-o5eum7dlLbCp7b7t .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-o5eum7dlLbCp7b7t #compositionEnd,#mermaid-svg-o5eum7dlLbCp7b7t .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-o5eum7dlLbCp7b7t #dependencyStart,#mermaid-svg-o5eum7dlLbCp7b7t .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-o5eum7dlLbCp7b7t #dependencyStart,#mermaid-svg-o5eum7dlLbCp7b7t .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-o5eum7dlLbCp7b7t #extensionStart,#mermaid-svg-o5eum7dlLbCp7b7t .extension{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-o5eum7dlLbCp7b7t #extensionEnd,#mermaid-svg-o5eum7dlLbCp7b7t .extension{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-o5eum7dlLbCp7b7t #aggregationStart,#mermaid-svg-o5eum7dlLbCp7b7t .aggregation{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-o5eum7dlLbCp7b7t #aggregationEnd,#mermaid-svg-o5eum7dlLbCp7b7t .aggregation{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-o5eum7dlLbCp7b7t .edgeTerminals{font-size:11px;}#mermaid-svg-o5eum7dlLbCp7b7t :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Payment Pay(int amount) CreditCardPayment Pay(int amount) PayPalPayment Pay(int amount) PaymentContext -Payment* _payment PayAmount(int amount) SetPayment(Payment* payment) 实现
class Payment
{
public:virtual void Pay(int amount) 0; // 抽象支付方式virtual ~Payment() default;
};// 不同支付方式继承与同一个接口
class CreditCardPayment : public Payment
{
public:void Pay(int amount) override{std::cout Paying amount using CreditCard std::endl;}
};class PayPalPayment : public Payment
{
public:void Pay(int amount) override{std::cout Paying amount using PayPal std::endl;}
};class PaymentContext
{
private:Payment* _payment{};
public:void PayAmount(int amount){if (_payment) _payment-Pay(amount);}// 根据需要变更策略void SetPayment(Payment* payment) { _payment payment;}
};总结
特点模板方法模式策略模式定义将算法的固定部分提取到基类变化部分由子类实现。将不同算法封装成独立的类通过上下文类动态切换算法。设计意图通过基类定义算法框架将具体实现延迟到子类。通过将算法封装成独立的类使其能够在运行时动态替换。使用场景固定流程的多个步骤其中部分步骤的实现因子类不同而不同。多种算法可以互换且算法相对独立变化频繁。优点1. 代码复用性高。2. 易于扩展新功能。1. 符合开闭原则。2. 代码更加灵活易于维护和扩展。缺点1. 继承关系较复杂。2. 增加类的数量。1. 增加系统复杂度。2. 上下文类需要了解所有策略的细节。 博客主页主页 我的专栏C 我的githubgithub