当前位置: 首页 > news >正文

thinkphp大型网站开发公司企业员工培训

thinkphp大型网站开发,公司企业员工培训,重点培育学科建设网站,哈尔滨网站建设市场分析在对象的设计过程中,[决定把责任放在哪儿]即使不是最重要的事,也是最重要的事之一。 1 Move Method(搬移函数) 概述 你的程序中,有个函数与其所驻class之外的另一个class进行更多交流&#xff1…

在对象的设计过程中,[决定把责任放在哪儿]即使不是最重要的事,也是最重要的事之一。

1 Move Method(搬移函数)

概述

你的程序中,有个函数与其所驻class之外的另一个class进行更多交流:调用后者,或被后者调用。在该函数最常引用(指涉)的class中建立一个有着类似行为的新函数,将旧函数变成一个单纯的委托函数(delegating method),或是将旧函数完全移除;

动机

[函数搬移]是重构理论的支柱。

如果一个class有太多行为,或如果一个class与另一个class有太多合作而形成高度耦合(highly coupled),就应该搬移函数;

是否应该移动一个函数,这往往不是一个容易做出的决定,如果不能肯定是否应该移动一个函数,那么或许[移动这个函数与否]并不是那么重要。

范例

我们用一个表示[账户]的class来说明这项重构:

ContractedBlock.gifExpandedBlockStart.gifCode
 1 class Account
 2 {
 3     private AccountType _type;
 4     private int _daysOverdrawn;
 5 
 6     double overdraftCharge() //透支金计费
 7     {
 8         if (_type.isPremium())
 9         {
10             double result = 10;
11             if (_daysOverdrawn > 7)
12             {
13                 result += (_daysOverdrawn - 7* 0.85;
14             }
15             return result;
16         }
17         else
18         {
19             return _daysOverdrawn * 1.75;
20         }
21     }
22 
23     double bankCharge()
24     {
25         double result = 4.5;
26         if (_daysOverdrawn > 0)
27             result += overdraftCharge();
28         return result;
29     }
30 }
31 
32 class AccountType
33 {
34     public bool isPremium()
35     {
36         return true;
37     }
38 }


假设有数种账户,每一种都有自己的[透支金计费规则]。所以透支金计费方法我们不应该放在账户里,我们希望能够把透支金计费方法overdraftCharge()放到AccountType类中。

ContractedBlock.gifExpandedBlockStart.gifCode
 1 class Account
 2 {
 3     private AccountType _type;
 4     private int _daysOverdrawn;
 5 
 6     double bankCharge()
 7     {
 8         double result = 4.5;
 9         if (_daysOverdrawn > 0)
10             result += _type.overdraftCharge(_daysOverdrawn);
11         return result;
12     }
13 }
14 class AccountType
15 {
16     public double overdraftCharge(int daysOverdrawn) //透支金计费
17     {
18         if (isPremium())
19         {
20             double result = 10;
21             if (daysOverdrawn > 7)
22             {
23                 result += (daysOverdrawn - 7* 0.85;
24             }
25             return result;
26         }
27         else
28         {
29             return daysOverdrawn * 1.75;
30         }
31     }
32 
33     public bool isPremium()
34     {
35         return true;
36     }
37 }


上面,我们把透支金计费方法移到了账户类型AccountType类中,这样对于不同的账户透支金计费规则,可以使用多态来实现它的计费,而账户类只需要一个接口就可以。

另外,对此例中被移函数,只取用(指涉)了一个值域(_daysOverdrawn),所以我只需要将这个值域作为参数传给target method就可以了。如果被移函数调用了Account中的另一个函数的话,就不能这么简单的处理了,这种情况我必须将source object传递给teget method。

如果target method需要太多source object特性,就得进一步重构。通常这种情况下应该分解target method,并将其中一部分移回source class;

备注

target method需要使用source class特性的时候,有四种选择:

1 将这个特性也移到target class

2 建立或使用一个从target classsource class的引用;

3 source class当作参数传给target method

4 如果所需特性是个变量,将它作为参数传给target method

 

很明显,上述用的是第四种。具体用哪种看实际情况。

2 Move Field(搬移值域)

概述

你的程序中,某个field被其所驻class之外的另一个class更多地用到。那么在target class中建立一个new field,修改source field的所有用户,令它们必胜new field

动机

classes之间移动状态(states)和行为,是重构过程中必不可少的措施。如果对于一个field(值域),在其所驻class之外的另一个class中有更多函数使用了它,就可以考虑搬移这个field。所谓[使用]可能是通过设值/取值(setting/getting)函数间接进行。

范例

下面是Account class的部分代码:

ContractedBlock.gifExpandedBlockStart.gifCode
class Account
{
    
private AccountType _type;
    
private double _interestRate;

    
double interestForAmountDays(double amount, int days)
    {
        
return _interestRate * amount * days / 365;
    }
}
class AccountType
{
}

 

每种账户类型的利率不同,所以我想把表示利率的_interestRate搬移到AccountType中去。

ContractedBlock.gifExpandedBlockStart.gifCode
class Account
{
    
private AccountType _type;

    
double interestForAmountDays(double amount, int days)
    {
        
return _type.InterestRate * amount * days / 365;
    }
}
class AccountType
{
    
private double _interestRate;

    
public double InterestRate
    {
        
get { return _interestRate; }
        
set { _interestRate = value; }
    }
}

 

3 Extract Class(提炼类)

概述

某个class做了应该由两个classes做的事,建立一个新class,将相关的值域和函数从旧class搬移到新class

动机

一个class应该是一个清楚的抽象(abstract),处理一些明确的责任。

 

在实际工作中,class会不断成长扩展。你会在这加入一些功能,在那加入一些数据,给某个class添加一项新责任时,你会觉得不值得为这项责任分离出一个单独的class。于是,随着责任的不断增加,这个class会变得过份复杂。

 

如果某些数据和某些函数总是一起出现,如果某些数据经常同时变化甚至彼此相依,这就表示你应该将它们分离出去。

范例

从一个简单的Person class开始:

ContractedBlock.gifExpandedBlockStart.gifCode
class Person
{
    
private string name;

    
public string Name
    {
        
get { return name; }
    }

    
private string officeAreaCode;

    
public string OfficeAreaCode
    {
        
get { return officeAreaCode; }
        
set { officeAreaCode = value; }
    }

    
private string officeNumber;

    
public string OfficeNumber
    {
        
get { return officeNumber; }
        
set { officeNumber = value; }
    }

    
public string GetTelephoneNumber()
    {
        
return ("(" + officeAreaCode + ")" + officeNumber);
    }
}

 

这上面例子中,我们可以将[与电话号码相关]的行为分离到一个独立class中,如下所示:

ContractedBlock.gifExpandedBlockStart.gifCode
class Person
{
    
private TelephoneNumber officeTelephone = new TelephoneNumber();

    
private string name;

    
public string Name
    {
        
get { return name; }
    }

    
public string GetTelephoneNumber()
    {
        
return officeTelephone.GetTelephoneNumber();
    }

}
class TelephoneNumber
{
    
public string GetTelephoneNumber()
    {
        
return ("(" + officeAreaCode + ")" + officeNumber);
    }

    
private string officeAreaCode;

    
public string OfficeAreaCode
    {
        
get { return officeAreaCode; }
        
set { officeAreaCode = value; }
    }

    
private string officeNumber;

    
public string OfficeNumber
    {
        
get { return officeNumber; }
        
set { officeNumber = value; }
    }
}

 

4 Inline Class(将类内联化)

概述

正好与Extract class相反,如果你的某个class没有做太多事情(没有承担足够责任),就可以将class的所有特性搬移到另一个class中,然后移除原class

动机

如果一个class不再承担足够的责任、不再有单独存在的理由,就应该挑选这一[萎缩class]的最频繁的用户(也是个class),以Inline Class手法将[萎缩class]塞进去。

范例

Extract Class范例所示,可以将TelephoneNumber塞回到Person类去。

5 Hide Delegate(隐藏[委托关系])

概述

对于客户直接调用其server object(服务对象)的delegate class,在server端(某个class)建立客户所需的所有函数,用以隐藏委托关系(delegation)

动机

[封装]即使不是对象的最关键特征,也是最关键特征之一。[封装]意味着每个对象都应该尽可能少了解系统的其他部分。如此一来,一旦发生了变化,需要了解这一变化的对象就会比较少,这会使得变化比较容易进行。

 

如果某个客户调用了[建立于server object的某个值域基础之上]的函数,那么客户就必须知道这一委托对象(即server object的特殊值域)。万一委托关系发生变化,客户也得相应变化。你可以在server端放置一个简单的委托函数(delegate method),将委托关系隐藏起来,从而去除这种依存性。这么一来即使将来发生委托关系的变化,变化将被限制在server中,不会波及客户。

范例

我们从代表[人]的Person类和代表部门的Department类来看:

ContractedBlock.gifExpandedBlockStart.gifCode
class Person
{
    
private Department department;

    
public Department Department
    {
        
get { return department; }
        
set { department = value; }
    }
}

class Department
{
    
private string chargeCode;
    
private Person manager;

    
public Department(Person manager)
    {
        
this.manager = manager;
    }

    
public Person Manager
    {
        
get { return manager; }
    }
}

 

如果客户希望知道某人的经理是谁,他必须先取得这个人所属的部门Department对象:

manager = onePerson.Department.Manager;

这样的代码就对客户揭露了Department的工作原理,于是客户知道:Department用以追踪[经理]这条信息。我们可以在Person中建立一个简单的委托函数,对客户隐藏Department。

    public Person GetManager()

    {

        return department.Manager;

}

这样,客户希望知道某人的经理是谁,就可以这样调用:

manaer = onePerson.GetManager();

只要完成了对Department所有函数的委托关系,并相应修改了Person的所有客户,就可以移除Person中的Department访问属性。

6 Remove Middle Man(移除中间人)

概述

某个class做了过多的简单委托动作(simple delegation),让客户直接调用delegate(委托类)

动机

Hide Delegate中,我们隐藏了delegate object,这层封装虽然使得客户只关心server object类,但同时它也付出了一定代价:每当客户要使用delegate(受托类)的新特性时,你就必须在server端添加一个简单委托函数。随着delegate的特性(功能)越来越多,这一过程会让你痛苦不已。Server完全变成了一个[中间人],此时你就应该让客户直接调用delegate

范例

Hide Delegate中范例所示,做一个反向过程。

备注

什么程序的隐藏才是合适的,这很难说,你可以在系统运行过程中不断进行调整,随着系统的变化,[合适的隐藏度]这个尺度也相应改变。

7 Introduce Foreign Method(引入外加函数)

概述

你所使用的server class需要一个额外函数,但你无法修改这个class;这时可以在client class中建立一个函数,并以一个server class实体作为第一引数(argument)。

动机

你使用一个免费dll,它真得不错,为你提供了你想要的所有服务,而后,你又需要一个新服务,这个class却无法供应,如果这个dll是开源的,你有源码,那么你可以自行添加一个你想要的新函数,如果不是开源的,你就得在客户端编码,补足你要的那个函数。

范例

假如我需要跨过一个收费周期(billing period),原本代码像这样:

Date newStart = new Date(previousEnd.getYear(),

previousEnd.getMonth(),previousEnd.getDate() + 1);

我可以通过添加一个外加函数:

Date newStart = nextDay(previousEnd);

private Date nextDay(Date arg)

{

    return new Date(arg.getYear(),arg.getMonth(),arg.getDate() + 1);

}

备注

外加函数终归是权宜之计,如果有可能,仍然应该将这些函数搬移到它们的理想家园。

8 Introduce Local Extension(引入本地扩展)

概述

你所使用的server class需要一些额外函数,但你无法修改这个class

建立一个新class,使它包含这些额外函数,让这个扩展品成为source classsubclass(子类)或wrapper(外覆类)。

动机

对于Introduce Foreign Method来说,如果你需要的外加函数超过两个,就很难控制住它们了,所以,你需要将这些函数组织在一起,放到一个恰当地方去。

所谓local extension,是一个独立的class,但也是其extended classsubtype(不同于subclass,它和extended class并不一定存在严格的继承关系,只要能够提供extended class的所有特性即可)。

范例:使用Subclass(子类)

public class MyDateSub : Date
{
    
private Date nextDay()
    {
        
return new Date(getYear(),getMonth(),getDate() + 1);
    }
}

 

范例:使用Wrapper(外覆类)

ContractedBlock.gifExpandedBlockStart.gifCode
public class MyDateWrap
{
    
private Date original;

    
public MyDateWrap(Date arg)
    {
        original 
= arg;
    }

    
public int getYear()
    {
        
return original.getYear();
    }
    
public int getMonth()
    {
        
return original.getMonth();
    }
    
public int getDate()
    {
        
return original.getDate();
    }
    
private Date nextDay()
    {
        
return new Date(getYear(),getMonth(),getDate() + 1);
    }
}

 

转载于:https://www.cnblogs.com/wych/archive/2009/09/19/1569788.html

http://www.lbrq.cn/news/2759671.html

相关文章:

  • 做网站运营的女生多吗自己怎么做网站推广
  • 游戏网站建设的必要性深圳最新新闻事件今天
  • 重庆市项目经理在建查询南宁seo推广优化
  • 做房产信息网站许昌网站seo
  • 中山网红长沙网站seo诊断
  • 网站建设的功能需求希爱力的功效及副作用
  • 电影网站做seo建材企业网站推广方案
  • 网站建设读后感搜索引擎营销概念
  • 无锡网站制作公司排名官方进一步优化
  • 深圳有哪些网站开发公司网站推广软件免费版
  • 百度推广区域代理黑帽seo工具
  • 旅游网站系统设计重庆seo外包平台
  • wordpress外贸B2C建站泉州全网营销推广
  • 深圳 网站科技山西网络推广
  • 网站改版定位策划书今日热点新闻头条
  • 湖北网络建设公司网站南京今天重大新闻事件
  • wordpress 最新漏洞班级优化大师官方网站
  • 网站建设武汉谷歌浏览器搜索引擎入口
  • 做miui主题网站广告投放平台有哪些
  • 中交建设集团网站无排名优化
  • 网站系统维护要多久百度在全国有哪些代理商
  • 许昌做网站团队武汉seo网站推广
  • 网站seo策略网络营销的营销理念
  • 网站建设流程分为三个步骤国内免费推广产品的网站
  • 职业生涯规划大赛演讲稿5分钟深圳网站seo服务
  • 关于网站空间百度搜索页
  • 怎么样用ps做网站百度网页版网址
  • 成都市网站制作一站式网络营销
  • 网站与微信结合百度官网网站
  • 只做一种产品的网站百度推广怎么弄
  • 【Jenkins】03 - 自动构建和docker构建
  • 网站服务器使用免费SSL证书安全吗?
  • 开放最短路径优先协议
  • 机器学习的多种算法
  • 【redis、ruoyi-vue】基于ruoyi-vue实现数据redis的增删改查
  • C语言(12)——进阶函数