PHP设计格局之工厂形式,设计情势

  工厂情势(Factory pattern)和单例形式同样,是此外一种创设型形式。

【设计情势】

参照博客 
  《大话设计格局》Python版代码实现 
  二公斤种设计情势及其python完成

统一希图条件

IOS设计情势的六大统一企图规范之开放-关闭原则(OCP,Open-Close
Principle)

观察者(Observer)模式

阅览者格局涵盖:

  • 照会机制(notification)
  • KVO机制

  和单例形式区别的是,单例格局会创建和处理二个独门的种类的单纯对象,工厂方式则是用于创制各类分歧类型的类的多少个目的。

一、设计情势介绍

设计格局(Design 帕特terns)

  ——可复用面向对象软件的基本功

  设计格局(Design
pattern)是一套被一再使用、许多人清楚的、经过分类编目标、代码设计经验的下结论。使用设计情势是为着可接纳代码、让代码更易于被外人领会、保障代码可信赖性。
毫无疑问,设计形式于己于别人于系统都以多赢的,设计情势使代码编写制定真正工程化,设计形式是软件工程的基石,就如大厦的壹块块砖块同样。项目中创制的运用设计格局能够圆满的减轻多数主题材料,种种方式在未来中都有照看的法则来与之对应,每三个格局描述了三个在我们周边不断重复爆发的主题素材,以及该难点的中央化解方案,那也是它能被遍及应用的由来。

  克Rees多夫亚历克斯ander:“每三个形式描述了2个在大家周边不断重复爆发的标题,以及该难点的消除方案的主干。那样你就会2遍又三次地行使该方案而无需做重复劳动。”每1个设计形式系统地命名、解释和商量了面向对象系统中3个第一的和另行出现的统一准备。

  设计情势八个基本要素:格局名称、难题、化解方案、效果

文告机制(notification)

寄托机制是代理“壹对1”的对象之间的通讯,而通告机制是广播“1对多”的靶子之间的通讯;
行使手续

    // 通知名
    NSString *const notificationName = @"testName";

    // 发送通知
    [[NSNotificationCenter defaultCenter] postNotificationName:notificationName object:nil];

    // 注册通知,加入观察者
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(doSomethong) name:notificationName object:nil];

    // 移除观察者
    [[NSNotificationCenter defaultCenter] removeObserver:self];

厂子形式的得以达成

  轻巧的厂子形式由3片段构成:

  1. 空泛基类:类中定义抽象一些主意,用以在子类中完结;
  2. 接轨自抽象基类的子类:完结基类中的抽象方法;
  3. 工厂类:用以实例化对象。

  下边来一步步完结八个简约的厂子方式先后。

  首先要定义三个虚无基类:

// 定义抽象基类
abstract class People{

    // 定义抽象方法
    abstract public function work();
}

  扩大两个基类的贯彻:

class Coder extends People{

    public function work("程序员的工作是写代码");
}

class Teacher extends People{

    public function work("老师的工作是教书育人");
}

class Cook extends People{

    public function work("厨师的工作是做美味的菜肴");
}

  定义务工作厂类,用于得以实现创立不一致目的的必要:

//工厂类
Class Factory{

    //此方法根据参数创建需要的对象
    static function createInstance($job){
        $job = ucfirst($job);
        return new $job;
    }

}

  今后,能够运作代码试试:

$p = Factory::createInstance("Teacher");
$p->work();
// 程序输出:老师的工作是教书育人
$m = Factory::createInstance("Coder");
$m->work();
// 程序输出:程序员的工作是写代码
$w = Factory::createInstance("Cook");
$w->work();
// 程序输出:厨师的工作是做美味的菜肴

 

  或然,能够那样修改基类:

// 定义抽象基类
abstract class People{

    // 定义抽象方法
    abstract public function work();

    /*######################################*/
    //定义工厂方法,并使其不可继承
    static final function createInstance($job){
        $job = ucfirst($job);
        return new $job;
    }
    /*######################################*/
}

  此时,能够如此创设对象:

$p = People::createInstance("Teacher");
$p->work();
// 程序输出:老师的工作是教书育人

 

贰、设计情势分类

  精彩的《设计情势》壹书总结出二叁种设计情势,这2叁种形式又可归为,创设型、结构型和行为型3大类

二.一.创立型格局

PHP设计格局之工厂形式,设计情势。  后面讲过,社会化的分工更为细,自然在软件设计方面也是如此,因而对象的开创和目的的选用分别也就改为了必然趋势。因为对象的创造会消耗掉系统的大队人马财富,所以单独对目的的创办进行商讨,从而能够异常快地创立对象就是成立型情势要研究的主题素材。这里有多个实际的创造型情势可供探究,它们分别是:

简言之工厂情势(Simple Factory);

厂子方法格局(Factory Method);

抽象工厂形式(Abstract Factory);

主要创我格局(Builder);

原型形式(Prototype);

单例情势(Singleton)。

证实:严厉来讲,轻巧工厂格局不是GoF总计出来的二三种设计方式之壹。

借助于于继续的创制型形式:工厂方法格局
重视于整合的创立性格局:抽象工厂方式、创建者形式

二.贰 结构型格局

  在消除了目的的创设难点将来,对象的组合以及对象时期的信赖关系就成了开采人士关怀的症结,因为何统一准备目的的结构、承继和依赖性关系会潜移默化到持续程序的维护性、代码的健壮性、耦合性等。对象协会的设计很轻松反映出设计人士水平的高低,这里有柒个具体的结构型形式可供探究,它们各自是:

适配器形式(Adapter);

桥模式(Bridge);

整合格局(Composite);

装饰方式(Decorator);

外观方式(Facade);

享元格局(Flyweight)

代理格局(Proxy);

二.3 行为型方式

在目标的布局和目的的创设难题都解决了后头,就剩下对象的作为难点了,假诺目的的行事设计的好,那么对象的行事就能更清晰,它们之间的通力合作功用就能够增长,这里有11个具体的行为型情势可供讨论,它们各自是:

解释器格局(Interpreter)。

权利链情势(Chain of Responsibility);

命令形式(Command);

迭代器方式(Iterator);

中介者情势(Mediator);

备忘录形式(Memento);

观看者形式(Observer);

意况格局(State);

布署形式(Strategy);

访问者形式(Visitor);

模板方法格局(Template Method);

KVO机制

行使手续

    // 添加观察者
    [self.jack addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:nil];

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        self.jack.name = @"Tom";
    });
// 属性(keyPath)的值发生变化时,收到通知,调用以下方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"name"] && object == self.jack) {

        //change的使用:上文注册时,枚举为2个,因此可以提取change字典中的新、旧值的这两个方法
        NSLog(@"old:%@ new:%@",[change valueForKey:@"old"],
              [change valueForKey:@"new"]);

    }
}

参考
iOS 趣谈设计形式——公告

单例

应用场景:确定保证程序运维期某些类,唯有一份实例,用于开始展览财富共享调控。

优势:使用简便,延时求值,易于跨模块

神速原则:单壹职责标准

MVC

选拔场景:是一中国和欧洲常古老的设计情势,通过数据模型,调整器逻辑,视图展现将应用程序进行逻辑划分。

优势:使系统,档案的次序显明,职责分明,易于维护

代理格局

行使场景:当三个类的一些成效需求由其他类来达成,可是又不分明具体会是哪位类落成。

优势:解耦合

厂子格局

厂子情势的长处及应用情况

  优点:降低了程序的耦合度,方便日后的保卫安全及扩展。

  使用处境:

    1.当主次编写制定的时候,并不能显著在改造对象的时候其确切的对象类型,唯有到程序运营的时候才会规定。

    二.在不分明会某个许个管理操作的时候,如针对接收到的数额,管理的逻辑大概会不相同,或者以往还会加多新的操作。 

 

三. 设计方式的陆大条件

一、开闭原则(Open Close Principle)

  开闭原则正是说:3个软件实体如类、模块和函数应该对扩展开放,对修改关闭。即软件实体应尽恐怕在不变原有代码的事态下开始展览扩大。在程序须求开始展览拓展的时候,不能去修改原有的代码,达成2个热插拔的职能。所以一句话归纳正是:为了使程序的扩充性好,易于维护和晋级。想要达到那样的功力,大家要求选择接口和抽象类,前面包车型客车现实性陈设中我们会涉及那一点。

2、里氏替换原则(Liskov Substitution Principle)

  里氏替换原则(Liskov Substitution Principle
LSP)面向对象设计的大旨标准之壹。
里氏代换原则中说,任何基类能够现身的地点,子类一定能够现身。及具有引用基类(父类)的地方必须能透明地使用其子类的目的。LSP是持续复用的基本,唯有当衍生类能够替换掉基类,软件单位的作用不受到震慑时,基类能力真的被复用,而衍生类也能够在基类的根底上平添新的行事。里氏代换原则是对“开-闭”原则的补给。落成“开-闭”原则的关键步骤正是抽象化。而基类与子类的一连关系就是抽象化的切实得以达成,所以里氏代换原则是对达成抽象化的具体步骤的正规化。——
From Baidu 百科

3、正视倒置原则(Dependence Inversion Principle)

  那些是开闭原则的根基,高层模块不该凭借低层模块,②者都应当借助其抽象;抽象不应有借助细节;细节应该依附抽象。换言之,要指向接口编制程序,而不是针对落到实处编制程序。具体内容:是对接口编制程序,依赖于肤浅而不借助于实际。

4、接口隔开原则(Interface Segregation Principle)

  那么些标准的意思是:使用多个隔绝的接口,比使用单个接口要好。照旧多少个下落类之间的耦合度的情趣,从此时大家来看,其实设计格局正是七个软件的设计观念,从大型软件框架结构出发,为了升高和保卫安全方便。总结回顾:使用多个尤其的接口,而不采用单一的总接口,即客户端不该依附这个它无需的接口;下跌正视,下降耦合。

五、迪米特法则(最少知道原则)(德姆eter Principle)

  为何叫最少知道原则,正是说:3个实体应当尽量少的与别的实体之间发生相互作用,使得系统功用模块相对独立。

6、单1职责标准:

  不要存在多于八个导致类更改的原因。通俗的说,即1个类只担任一项任务。

亚洲必赢官网 ,概念

工厂(比如,OperationFactory)
架空产品(比如,Operation)
具体产品(比如,OperationAdd)

肆、写在标准介绍设计形式从前

面向对象3大特点:封装,承接,多态

封装:
  1、把多少和函数包装在类里
  二、类的境界限制了1部极度边的走访 —》 私有品质

继续:消除代码复用 重写方法叫做:override 重写,复写

多态:父类可以象征子类

抽象类:
  抽象类不可能被实例化
  抽象类的空洞方法,必须在子类中完毕

接口:
  一种尤其的类,注解了若干措施,供给持续该接口的类必须兑现这一个艺术。
  作用:限制继承袭口的类的方法的名号及调用格局;隐藏了类的当中贯彻。
  接口就是1种浮泛的基类(父类),限制承接它的类必须兑现接口中定义的一点方法

亚洲必赢官网 1亚洲必赢官网 2

from abc import abstractmethod, ABCMeta

#定义抽象类
class Payment(metaclass=ABCMeta):
    @abstractmethod
    def pay(self, money):
        """支付方法,参数money,每个继承的类都要实现这个方法"""
        pass

#实现Payment接口
class Alipay(Payment):
    def pay(self, money):
        print("支付宝支付%s元"%money)


class ApplePay(Payment):
    def pay(self, money):
        print("苹果支付%s元"%money)


class WechatPay(Payment):
    def pay(self, money):
        print("微信支付%s元"%money)


def func(x):
    x.pay(100)

接口应用代码举个例子

简短工厂

定义:“专门定义三个类来顶住成立其余类的实例,被创制的实例通常抱有协同的父类。

事实上正是由八个工厂类,依据传入的参数,动态的垄断(monopoly)创制出哪三个出品类的实例。
角色
壹.工厂类剧中人物(比方,OperationFactory):简单工厂格局的骨干,担任遵照传入的参数来实例化具体的成品实例。

2.华而不实产品角色(比如,Operation):常常是工厂爆发具体类的父类(大概是现实类落成的接口)。

三.切实产品剧中人物(举个例子,OperationAdd):轻巧工厂方式所开创的此外对象都是以此角色的实例。

流程:工厂类,发生实际的产品实例(承继自基类,一碗水端平写基类的秘诀),使用那么些产品实例,调用重写的基类的措施,完结须要。

    Operation* oper;
    oper = [OperationFactory createOperate:self.operationTextField.text];
    oper.firstNum = [strFirstNum doubleValue];
    oper.secondNum = [strSecondNum doubleValue];
    self.resultTextField.text = [NSString stringWithFormat:@"%f",[oper getResult]];

可取:低耦合,每一个类担任单独的效用

五、各个设计格局 

1、简单工厂形式

亚洲必赢官网 3

创造对象放在了工厂类中,而不是再爆出在外边,通过工厂类达成全部操作。

亚洲必赢官网 4亚洲必赢官网 5

from abc import abstractmethod, ABCMeta
#定义支付方法的抽象类
class Payment(metaclass=ABCMeta):
    @abstractmethod
    def pay(self, money):
        pass
#定义不同的支付方法
class Alipay(Payment):
    def __init__(self, enable_yuebao=False):
        self.enable_yuebao = enable_yuebao

    def pay(self, money):
        if self.enable_yuebao:
            print("余额宝支付%s元" % money)
        else:
            print("支付宝支付%s元" % money)


class ApplePay(Payment):
    def pay(self, money):
        print("苹果支付%s元" % money)

#简单工厂模式,一个工厂定义一个生产方式。通过传入的参数判断,不同的支付类型
class PaymentFactory:
    def create_payment(self, method):
        if method == "alipay":
            return Alipay()
        elif method == "applepay":
            return ApplePay()
        elif method == "yuebao":
            return Alipay(enable_yuebao=True)
        else:
            raise NameError(method)

f = PaymentFactory()
p = f.create_payment("alipay")
p.pay(100)

归纳工厂格局

贰、工厂方法方式

 亚洲必赢官网 6

切实工厂重视具体产品

内容:定义一个用于创造对象的接口(工厂接口),让子类决定实例化哪3个产品类。
角色:
  抽象工厂角色(Creator)
  具体育工作厂剧中人物(Concrete Creator)
  抽象产品剧中人物(Product)
  具体产品剧中人物(Concrete Product)
形式特点:定义一个用来创制对象的接口,让子类决定实例化哪三个类。那使得叁个类的实例化延迟到其子类。
  那么些情势和总结工厂有分别,轻易工厂格局唯有三个厂子,工厂方法情势相比轻易工厂格局将各种具体产品都对应了一个具体育工作厂。

适用场景:
  供给生产各类、多量繁杂对象的时候
  需求下跌耦合度的时候
  当系统中的产品体系须求平日扩张的时候
优点:
  种种具体产品都对应2个有血有肉工厂类,无需修改工厂类代码
  隐藏了目标创制的落成细节
缺点:
  每扩张多少个有血有肉产品类,就务须扩张1个心心相印的切实工厂类

 

内容:不直接向客户端揭露目的创立的得以落成细节,而是通过三个工厂类来承担创立产品类的实例。
角色:
  工厂剧中人物(Creator)
  抽象产品剧中人物(Product)
  具体产品角色(Concrete Product)
优点:
  隐藏了目的创造的贯彻细节,工厂根据条件发出分歧功效的类。
  客户端无需修改代码
缺点:
  违反了纯粹职分标准,将创造逻辑二种到一个厂子类里
  当增多新产品时,要求修改工厂类代码,违反了开闭原则

亚洲必赢官网 7亚洲必赢官网 8

from abc import abstractmethod, ABCMeta

#定义支付类型的抽象类
class Payment(metaclass=ABCMeta):
    @abstractmethod
    def pay(self, money):
        pass

#继承支付抽象类
class Alipay(Payment):
    def pay(self, money):
        print("支付宝支付%s元" % money)


class ApplePay(Payment):
    def pay(self, money):
        print("苹果支付%s元"%money)

#定义工厂的抽象类,用于支付类的生产
class PaymentFactory(metaclass=ABCMeta):
    @abstractmethod
    def create_payment(self):
        pass

#继承工厂抽象类,具体工厂负责具体的产品
class AlipayFactory(PaymentFactory):
    def create_payment(self):
        return Alipay()

class ApplePayFactory(PaymentFactory):
    def create_payment(self):
        return ApplePay()

#具体使用,利用具体工厂的对象 实例 具体支付的对象 然后 调用支付方法
# 用户输入
# 支付宝,120 
af = AlipayFactory() 
ali = af.create_payment()
ali.pay(120)

工厂方法格局

三、抽象工厂形式

 亚洲必赢官网 9

计划:提供多少个创建一体系有关或互相注重对象的接口,而无需点名它们具体的类。

适用性:

  三个体系要独自于它的产品的创制、组合和象征时。

  二个种类要由多少个产品多元中的2个来布置时。

  当您要重申1多种有关的制品对象的安插性以便进行共同使用时。

  当您提供二个成品类库,而只想体现它们的接口而不是达成时。

剧情:定义2个厂子类接口,让工厂子类来开创一多级相关或互相重视的对象。
例:生产1部手提式有线电话机,要求手提式有线电话机壳、CPU、操作系统3类对象实行组装,个中每类对象都有例外的等级次序。对各类具体育工作厂,分别生育1部手提式无线电话机所急需的多少个目的。
角色:
  抽象工厂剧中人物(Creator)
  具体育工作厂剧中人物(Concrete Creator)
  抽象产品剧中人物(Product)
  具体产品剧中人物(Concrete Product)
  客户端(Client)

相比工厂方法格局,抽象工厂方式中的每种具体工厂都生产一套产品。

适用场景:
  系统要独自于产品的创设与重组时
  重申1类别有关的出品对象的规划以便实行联合使用时
  提供一个出品类库,想隐藏产品的切实可行落到实处时
优点:
  将客户端与类的现实贯彻相分离
  每一个工厂创建了二个全部的制品数不尽,使得易于交流产品点不清
  有利于产品的壹致性(即产品里面的自律关系)
缺点:
  难以支撑新品类的(抽象)产品

亚洲必赢官网 10亚洲必赢官网 11

from abc import abstractmethod, ABCMeta

# ------抽象产品------
class PhoneShell(metaclass=ABCMeta):
    @abstractmethod
    def show_shell(self):
        pass

class CPU(metaclass=ABCMeta):
    @abstractmethod
    def show_cpu(self):
        pass

class OS(metaclass=ABCMeta):
    @abstractmethod
    def show_os(self):
        pass


# ------抽象工厂------
class PhoneFactory(metaclass=ABCMeta):
    @abstractmethod
    def make_shell(self):
        pass

    @abstractmethod
    def make_cpu(self):
        pass

    @abstractmethod
    def make_os(self):
        pass


# ------具体产品------
class SmallShell(PhoneShell):
    def show_shell(self):
        print("普通手机小手机壳")

class BigShell(PhoneShell):
    def show_shell(self):
        print("普通手机大手机壳")

class AppleShell(PhoneShell):
    def show_shell(self):
        print("苹果手机壳")


class SnapDragonCPU(CPU):
    def show_cpu(self):
        print("骁龙CPU")


class MediaTekCPU(CPU):
    def show_cpu(self):
        print("联发科CPU")


class AppleCPU(CPU):
    def show_cpu(self):
        print("苹果CPU")


class Android(OS):
    def show_os(self):
        print("Android系统")


class IOS(OS):
    def show_os(self):
        print("iOS系统")


# ------具体工厂------

class MiFactory(PhoneFactory):
    def make_cpu(self):
        return SnapDragonCPU()

    def make_os(self):
        return Android()

    def make_shell(self):
        return BigShell()


class HuaweiFactory(PhoneFactory):
    def make_cpu(self):
        return MediaTekCPU()

    def make_os(self):
        return Android()

    def make_shell(self):
        return SmallShell()


class IPhoneFactory(PhoneFactory):
    def make_cpu(self):
        return AppleCPU()

    def make_os(self):
        return IOS()

    def make_shell(self):
        return AppleShell()


# ------客户端------
class Phone:
    def __init__(self, cpu, os, shell):
        self.cpu = cpu
        self.os = os
        self.shell = shell

    def show_info(self):
        print("手机信息:")
        self.cpu.show_cpu()
        self.os.show_os()
        self.shell.show_shell()

# ------创造产品------
def make_phone(factory):
    cpu = factory.make_cpu()
    os = factory.make_os()
    shell = factory.make_shell()
    return Phone(cpu, os, shell)

p1 = make_phone(HuaweiFactory())
p1.show_info()

虚幻工厂方式

四、建造者格局

 亚洲必赢官网 12

意图:将一个复杂对象的营造与它的表示分离,使得同1的创设进程能够创造差别的代表。

适用场景:
  当创设复杂对象的算法(Director)应该单独于该对象的组成都部队分(Builder)以及它们的装配方式时
  当组织过程允许被协会的靶子有例外的意味时(区别Builder)。
角色:
  抽象建造者(Builder)
  具体建造者(Concrete Builder)
  指挥者(Director)
  产品(Product)

  建造者格局与画饼充饥工厂情势相似,也用来创立复杂对象。首要分裂是建造者形式首要一步步协会1个参差不齐对象,而空虚工厂格局注重于多个体系的制品对象

优点:
  隐藏了叁个出品的内部结交涉装配进程
  将协会代码与代表代码分开
  能够对组织进度进展更加小巧的主宰

亚洲必赢官网 13亚洲必赢官网 14

from abc import abstractmethod, ABCMeta

#------产品------
class Player:
    def __init__(self, face=None, body=None, arm=None, leg=None):
        self.face = face
        self.arm = arm
        self.leg = leg
        self.body = body

    def __str__(self):
        return "%s, %s, %s, %s" % (self.face, self.arm, self.body, self.leg)


#------建造者------
class PlayerBuilder(metaclass=ABCMeta):
    @abstractmethod
    def build_face(self):
        pass
    @abstractmethod
    def build_arm(self):
        pass
    @abstractmethod
    def build_leg(self):
        pass
    @abstractmethod
    def build_body(self):
        pass
    @abstractmethod
    def get_player(self):
        pass

# 建造生产的类
class BeautifulWomanBuilder(PlayerBuilder):
    def __init__(self):
        self.player = Player()
    def build_face(self):
        self.player.face = "漂亮脸蛋"
    def build_arm(self):
        self.player.arm="细胳膊"
    def build_body(self):
        self.player.body="细腰"
    def build_leg(self):
        self.player.leg="长腿"
    def get_player(self):
        return self.player

# 用于生产 产品的类
class PlayerDirector:
    def build_player(self, builder):
        builder.build_body()
        builder.build_arm()
        builder.build_leg()
        builder.build_face()
        return builder.get_player()

#客户端
director = PlayerDirector()
builder = BeautifulWomanBuilder()
p = director.build_player(builder)
print(p)

建造者形式

五、单例情势

 亚洲必赢官网 15

图谋:创设叁个类,保障1个类唯有2个实例,并提供三个访问它的大局访问点。单例相当于是全局变量,内部的点子只怕会被改变

角色:
  单例(Singleton)
适用场景
  当类只可以有二个实例而且客户能够从二个分明的访问点访问它时;
  当以此唯一实例应该是经过子类化可扩展的,并且客户应该不要更动代码就能够运用五个扩展的实例时。
优点:
  对唯壹实例的受控访问
  单例相当于全局变量,但谨防了命名空间被污染
与单例形式功能相似的定义:全局变量、静态变量(方法)

亚洲必赢官网 16亚洲必赢官网 17

class Singleton(object):
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, "_instance"):
            cls._instance = super(Singleton, cls).__new__(cls)
        return cls._instance

class MyClass(Singleton):
    def __init__(self, name):
            self.name = name


a = MyClass("a")

print(a)
print(a.name)

b = MyClass('b')
#
print(b)
print(b.name)
b.name = 'xxx'
#
print(a)
print(a.name)

单例格局

亚洲必赢官网 18亚洲必赢官网 19

单例模式:

    单例模式  每次只实例化一个对象!造对象的过程是__new__方法,给对象传数据是__init__的方法,做成一个实例!
    类不管怎样创建多个实例,对象都会以第一个实例为准

#方式一:文件导入,文件内创建一个对象,通过这个对象导入方法

#方式二:通过静态方法实例化对象

class Foo:

    # 定义静态变量实例
    _instance = None

    def __init__(self):
        pass

    @staticmethod
    def get_instance(cls):
        if cls._instance:
            return cls._instance
        else:
            obj = cls()
            cls._instance = obj
            return obj

#方式三: __new__ 

class Foo(object):
    _instance = None

    def __init__(self):
        pass

    def __new__(cls, *args, **kwargs):
        if cls._instance:
            return cls._instance
        else:
            obj = object.__new__(cls, *args, **kwargs)
            cls._instance = obj
            return obj

用途:
    - 自定义curb组件时,对于类构建的信息,仅需一个实例
    - 发布文章,特殊字符的过滤: KindEditor

单例形式深究

6、适配器情势

 亚洲必赢官网 20

企图:将多个类的接口调换到客户愿意的另多个接口。适配器方式使得原本由于接口不相配而不可能共同工作的那几个类能够协同坐班。
角色:
  目的接口(Target)
  待适配的类(Adaptee)
  适配器(Adapter)
两种完毕格局:
  类适配器:使用多一连
  对象适配器:使用组合

适用场景:
  你想利用2个早已存在的类,而它的接口不合乎您的供给;
  你想创设1个得以复用的类,该类能够与别的不相干的类或不足预感的类(即那一个接口大概不自然包容的类)协同职业。
  (对象适配器)想选取部分业已存在的子类,但不容许对每多少个都进行子类化以12分它们的接口。对象适配器能够适配它的父类接口。

类适配器和目的适配器有两样的衡量。
类适配器规则:
  使用3个实际的Adapter类对Adaptee和Target实行相配。结果是当大家想要相配三个类以及独具他的子类时,类艾达pter将无法胜任职业。
  使用Adapter能够重定义Adapter的局地作为,因为Adapter是Adaptee的2个子类。
  仅仅引进一个目标,并无需额外的指针以直接获得adaptee.
目的适配器规则:
  允许二个Adapter与两个Adaptee —
即Adaptee本人以及它的有着子类(倘使有子类的话)1一起时职业。Adapter也得以一次给持有的Adaptee增多作用。
  使得重定义 艾达ptee 的表现比较不方便。那亟需生成Adaptee的子类并且使得
Adapter 引用这几个子类而不是引用Adaptee本人。

亚洲必赢官网 21亚洲必赢官网 22

from abc import abstractmethod, ABCMeta


class Payment(metaclass=ABCMeta):
    @abstractmethod
    def pay(self, money):
        raise NotImplementedError


class Alipay(Payment):
    def pay(self, money):
        print("支付宝支付%s元"%money)


class ApplePay(Payment):
    def pay(self, money):
        print("苹果支付%s元"%money)

#------待适配类------
class WechatPay:
    def huaqian(self, money):
        print("微信支付%s元"%money)

#------类适配器------
class RealWeChatPay(Payment, WechatPay):
    def pay(self, money):
        return self.huaqian(money)


#------对象适配器------
class PayAdapter(Payment):
    def __init__(self, payment):
        self.payment = payment #类的一个对象

    def pay(self, money):
        return self.payment.huaqian(money)


RealWeChatPay().pay(100)
#PayAdapter(WechatPay()).pay(1000)

适配器方式

亚洲必赢官网 23亚洲必赢官网 24

from abc import abstractmethod, ABCMeta

class Payment(metaclass=ABCMeta):
    @abstractmethod
    def pay(self, money):
        """支付方法,参数money"""
        pass

#实现Payment接口
class Alipay(Payment):
    def pay(self, money):
        print("支付宝支付%s元"%money)


class ApplePay(Payment):
    def pay(self, money):
        print("苹果支付%s元"%money)

class PaymentX(metaclass=ABCMeta):
    @abstractmethod
    def zhifu(self, money):
        """支付方法,参数money"""
        pass

class WechatPay(PaymentX):
    def zhifu(self, money):
        print("微信支付%s元"%money)

class CreditCardPay(PaymentX):
    def zhifu(self, money):
        print("信用卡支付%s元" % money)

class PaypalPay(PaymentX):
    def zhifu(self, money):
        print("信用卡支付%s元" % money)

#类适配器
class RealWechatPay(Payment, WechatPay):
    def pay(self, money):
        self.zhifu(money)

p = RealWechatPay()
p.pay(100)

#对象适配器
class RealPay(Payment):
    def __init__(self, payment_cls):
        self.__a = payment_cls()
    def pay(self, money):
        self.__a.zhifu(money)

def test_payment(p):
    p.pay(100)

test_payment(RealPay(CreditCardPay))

适配器

⑦、组合模式

 亚洲必赢官网 25

用意:将目的组合成树形结构以代表“部分-全部”的档期的顺序结构。组合情势使得用户对单个对象和组成对象的选取具备1致性。
角色:
  抽象组件(Component)
  叶子组件(Leaf)
  复合组件(Composite)
  客户端(Client)

适用场景:
  表示对象的“部分-全体”等级次序结构(特别是构造是递归的)
  希望用户忽略组合对象与单个对象的不等,用户统1地应用组合结构中的全体目标
优点:
  定义了含蓄基本目的和构成对象的类档期的顺序结构
  简化客户端代码,即客户端能够同样地应用组合对象和单个对象
  更便于扩展新类型的机件
缺点:
  很难限制组合中的组件

亚洲必赢官网 26亚洲必赢官网 27

from abc import abstractmethod, ABCMeta

class Graphic(metaclass=ABCMeta):
    @abstractmethod
    def draw(self):
        pass

    @abstractmethod
    def add(self, graphic):
        pass

    def getchildren(self):
        pass

# 图元

class Point(Graphic):
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def draw(self):
        print(self)

    def add(self, graphic):
        raise TypeError

    def getchildren(self):
        raise TypeError

    def __str__(self):
        return "点(%s, %s)" % (self.x, self.y)


class Line(Graphic):
    def __init__(self, p1, p2):
        self.p1 = p1
        self.p2 = p2

    def draw(self):
        print(self)

    def add(self, graphic):
        raise TypeError

    def getchildren(self):
        raise TypeError

    def __str__(self):
        return "线段[%s, %s]" % (self.p1, self.p2)


class Picture(Graphic):
    def __init__(self):
        self.children = []

    def add(self, graphic):
        self.children.append(graphic)

    def getchildren(self):
        return self.children

    def draw(self):
        print("------复合图形------")
        for g in self.children:
            g.draw()
        print("------END------")


pic1 = Picture()
point = Point(2,3)
pic1.add(point)
pic1.add(Line(Point(1,2), Point(4,5)))
pic1.add(Line(Point(0,1), Point(2,1)))

pic2 = Picture()
pic2.add(Point(-2,-1))
pic2.add(Line(Point(0,0), Point(1,1)))

pic = Picture()
pic.add(pic1)
pic.add(pic2)

pic.draw()
pic1.draw()
point.draw()

重组形式

八、代理情势

亚洲必赢官网 28

筹划:为别的对象提供一种代理以调控对那一个目标的造访。在必要用比较通用和复杂的目的指针代替轻巧的指针的时候,使用Proxy方式。
角色:
  抽象实体(Subject)
  实体(RealSubject)
  代理(Proxy)
适用场景:
  远程代理:为远程的目的提供代理。3个目的在不一样的地点空间提供一些代表。
  虚代理:依据必要创制非常的大的靶子。
  爱慕代理:调控对原本对象的拜会,用于对象有两样访问权限期。爱抚代理用于对象应该有例外的走访权限的时候。举例,在Choices
操作系统[ CIRM93]中KemelProxies为操作系统对象提供了访问尊敬。 
  智能辅导(斯Matt Reference
)替代了大致的指针,它在走访对象时实行一些外加操作。
它的头角峥嵘用途包蕴:对针对性实际目的的引用计数,那样当该对象未有引用时,能够自行释放它。
优点:
  远程代理:能够隐藏对象位于远程地址空间的实际情况
  虚代理:能够开始展览优化,举个例子依据必要成立对象
  珍贵代理:允许在拜访二个对象时有一些附加的内务管理

  当第壹回引用贰个水滴石穿对象时,将它装入内部存款和储蓄器。在造访三个实际目的前,检查是还是不是早已锁定了它,以确定保证其余对象不能够改动它。

亚洲必赢官网 29亚洲必赢官网 30

from abc import ABCMeta, abstractmethod

class Subject(metaclass=ABCMeta):
    @abstractmethod
    def get_content(self):
        pass
    def set_content(self, content):
        pass

#文件操作,获取文件内容和设置
class RealSubject(Subject):
    def __init__(self, filename):
        self.filename = filename
        print("读取%s文件内容"%filename)
        f = open(filename)
        self.content = f.read()
        f.close()

    def get_content(self):
        return self.content

    def set_content(self, content):
        f = open(self.filename, 'w')
        f.write(content)
        self.content = content
        f.close()

class ProxyA(Subject):
    def __init__(self, filename):
        self.subj = RealSubject(filename)

    def get_content(self):
        return self.subj.get_content()


#---虚代理
class ProxyB(Subject):
    def __init__(self, filename):
        self.filename = filename
        self.subj = None

    def get_content(self):
        if not self.subj:
            self.subj = RealSubject(self.filename)
        return self.subj.get_content()

x = ProxyB('abc.txt')
"""abc.txt 内文本 hello world"""
#print(x.get_content())


# --保护代理
class ProxyC(Subject):
    def __init__(self, filename):
        self.subj = RealSubject(filename)

    def get_content(self):
        self.subj.get_content()

    def set_content(self, content):
        raise PermissionError

filename = "abc.txt"
username = input()
if username!="somebody":
    p = ProxyC(filename)
else:
    p = ProxyA(filename)

print(p.get_content())

代办方式

九、义务链情势

 亚洲必赢官网 31

妄想:使多个目的都有时机管理请求,从而防止请求的发送者和接收者之间的耦合关系。将这么些目的连成一条链,并顺着那条链传递该请求,直到有四个目的管理它截至。
角色:
  抽象管理者(Handler)
  具体管理者(ConcreteHandler)
  客户端(Client)
适用场景:
  有多个对象能够拍卖1个呼吁,哪个目的管理由运维时间调控制
  在不鲜明接收者的气象下,向多少个对象中的三个交由三个呼吁
  可处理二个呼吁的目的集结应被动态钦赐。
优点:
  下降耦合度:一个对象无需精晓是其他哪三个目的管理其请求
缺点:
  请求不保障被选择:链的末端未有拍卖或链配置错误
例:
  请假部门批准:leader —> 部门老董 —> 总主任
  Javascript事件浮升机制

亚洲必赢官网 32亚洲必赢官网 33

from abc import ABCMeta, abstractmethod

class Handler(metaclass=ABCMeta):
    @abstractmethod
    def handle_leave(self, day):
        pass

class GeneralManagerHandler(Handler):
    def handle_leave(self, day):
        if day < 10:
            print("总经理批准%d天假"%day)
        else:
            print("呵呵")

class DepartmentManagerHandler(Handler):
    def __init__(self):
        self.successor = GeneralManagerHandler()
    def handle_leave(self, day):
        if day < 7:
            print("部门经理批准%d天假"%day)
        else:
            print("部门经理无权准假")
            self.successor.handle_leave(day)


class ProjectDirectorHandler(Handler):
    def __init__(self):
        self.successor = DepartmentManagerHandler()
    def handle_leave(self, day):
        if day < 3:
            print("项目主管批准%d天假"%day)
        else:
            print("项目主管无权准假")
            self.successor.handle_leave(day)


day = 9
h = ProjectDirectorHandler()
h.handle_leave(day)

职务链方式(请假流程)

亚洲必赢官网 34亚洲必赢官网 35

class Handler(metaclass=ABCMeta):
    @abstractmethod
    def add_event(self, func):
        pass

    @abstractmethod
    def handle(self):
        pass

class BodyHandler(Handler):
    def __init__(self):
        self.func = None

    def add_event(self, func):
        self.func = func

    def handle(self):
        if self.func:
            return self.func()
        else:
            print("已到最后一级,无法处理")


class ElementHandler(Handler):
    def __init__(self, successor):
        self.func = None
        self.successor = successor

    def add_event(self, func):
        self.func = func

    def handle(self):
        if self.func:
            return self.func()
        else:
            return self.successor.handle()

# 客户端

# <body><div><a>

body = {'type': 'body', 'name': 'body', 'children': [], 'father': None}

div = {'type': 'div', 'name': 'div', 'children': [], 'father': body}

a = {'type': 'a', 'name': 'a', 'children': [], 'father': div}

body['children'].append(div)
div['children'].append(a)

body['event_handler'] = BodyHandler()
div['event_handler'] = ElementHandler(div['father']['event_handler'])
a['event_handler'] = ElementHandler(a['father']['event_handler'])

def attach_event(element, func):
    element['event_handler'].add_event(func)

def func_div():
    print("这是给div的函数")

def func_a():
    print("这是给a的函数")

def func_body():
    print("这是给body的函数")

#attach_event(div, func_div)
attach_event(a, func_a)
attach_event(body, func_body)

a['event_handler'].handle()

模仿js事件管理

拾、迭代器情势

亚洲必赢官网 36

用意:提供1种办法顺序访问3个汇合对象中的各种要素,而又无需揭露该目的的内部表示

适用性:
  访问1个集中对象的剧情而没有须要揭露它的内部表示。
  协助对集中对象的多样遍历。
  为遍历分裂的集合结构提供二个联合的接口(即, 补助多态迭代)。

落成情势:__iter__、__next__

亚洲必赢官网 37亚洲必赢官网 38

class Range:

    def __init__(self,start,end):
        self.start = start
        self.end = end

    def __iter__(self): #将对象转变成迭代器
        return self

    def __next__(self): #自取值
        if self.start == self.end:
            raise StopIteration

        n = self.start
        self.start+=1
        return n

for i in Range(1,10):
    print(i)

迭代器方式

1一、观察者格局

 亚洲必赢官网 39

筹划:定义对象间的壹种壹对多的依赖关系,当2个目标的场地发生转移时, 全部依赖于它的目的都收获打点并被自动更新。观望者情势又称“公布-订阅”方式
角色:
  抽象宗旨(Subject)
  具体宗旨(ConcreteSubject)——公布者
  抽象观看者(Observer)
  具体观望者(ConcreteObserver)——订阅者
适用场景:
  当二个虚幻模型有两地点,个中1个地方正视于另一个方面。将那两边封装在单独对象中以使它们能够独家独立地改成和复用。
  当对3个对象的改观须要同时改造别的对象,而不知底具体有稍许对象有待改换。
  当1个目标必须通报其余对象,而它又不可能假定别的对象是哪个人。换言之,你不愿意那些目标是牢牢耦合的。
优点:
  目的和观看者之间的悬空耦合最小
  匡助广播通讯
缺点:
  八个观看者之间互不知道对方存在,由此3个观望者对核心的改造也许引致错误的换代。

亚洲必赢官网 40亚洲必赢官网 41

from abc import ABCMeta, abstractmethod

class Observer(metaclass=ABCMeta):
    @abstractmethod
    def update(self, notice):
        pass

class Notice:
    def __init__(self):
        self.observers = []

    def attach(self, obs):
        self.observers.append(obs)

    def detach(self, obs):
        self.observers.remove(obs)
        obs.company_info=None

    def notify(self):
        for obj in self.observers:
            obj.update(self)


class ManagerNotice(Notice):
    def __init__(self, company_info=None):
        super().__init__()
        self.__company_info = company_info

    @property
    def company_info(self):
        return self.__company_info

    @company_info.setter
    def company_info(self, info):
        self.__company_info = info
        self.notify()


class Manager(Observer):
    def __init__(self):
        self.company_info = None

    def update(self, noti):
        self.company_info = noti.company_info


notice = ManagerNotice()

abes = Manager()
dws = Manager()

# print(alex.company_info)
# print(wusir.company_info)

notice.attach(abes)
notice.attach(dws)
#
notice.company_info="公司运行良好"
#
# print(alex.company_info)
# print(wusir.company_info)

notice.company_info="公司将要上市"

print(abes.company_info)
print(dws.company_info)
#
notice.detach(dws)
# #
notice.company_info="公司要破产了,赶快跑路"
#
print(abes.company_info)
print(dws.company_info)

观望者格局

1二、战术情势

亚洲必赢官网 42

筹算:定义一密密麻麻的算法,把它们3个个打包起来,并且使它们可相互替换。本格局使得算法可单独于接纳它的客户而调换。
角色:
  抽象攻略(Strategy)
  具体战略(ConcreteStrategy)
  上下文(Context)
适用场景:
  许多有关的类仅仅是行为有异。“战略”提供了一种用多个表现中的三个表现来布置一个类的方法。
  供给利用3个算法的不等变体。比如,你可能会定义一些反映不1的半空中/时间权衡的算法。当这个变体达成为贰个算法的类档期的顺序时,能够选取政策方式。
  算法使用了客户端无需领会的多少。可使用政策情势以免止暴光复杂的、与算法相关的数据结构。
  3个类中的三种作为以五个尺码语句的花样存在,能够将那个表现封装如差异的宗旨类中。

亚洲必赢官网 43亚洲必赢官网 44

from abc import ABCMeta, abstractmethod
import random

class Sort(metaclass=ABCMeta):
    @abstractmethod
    def sort(self, data):
        pass


class QuickSort(Sort):
    def quick_sort(self, data, left, right):
        if left < right:
            mid = self.partition(data, left, right)
            self.quick_sort(data, left, mid - 1)
            self.quick_sort(data, mid + 1, right)

    def partition(self, data, left, right):
        tmp = data[left]
        while left < right:
            while left < right and data[right] >= tmp:
                right -= 1
            data[left] = data[right]
            while left < right and data[left] <= tmp:
                left += 1
            data[right] = data[left]
        data[left] = tmp
        return left

    def sort(self, data):
        print("快速排序")
        return self.quick_sort(data, 0, len(data) - 1)


class MergeSort(Sort):
    def merge(self, data, low, mid, high):
        i = low
        j = mid + 1
        ltmp = []
        while i <= mid and j <= high:
            if data[i] <= data[j]:
                ltmp.append(data[i])
                i += 1
            else:
                ltmp.append(data[j])
                j += 1

        while i <= mid:
            ltmp.append(data[i])
            i += 1

        while j <= high:
            ltmp.append(data[j])
            j += 1

        data[low:high + 1] = ltmp


    def merge_sort(self, data, low, high):
        if low < high:
            mid = (low + high) // 2
            self.merge_sort(data, low, mid)
            self.merge_sort(data, mid + 1, high)
            self.merge(data, low, mid, high)

    def sort(self, data):
        print("归并排序")
        return self.merge_sort(data, 0, len(data) - 1)


class Context:
    def __init__(self, data, strategy=None):
        self.data = data
        self.strategy = strategy

    def set_strategy(self, strategy):
        self.strategy = strategy

    def do_strategy(self):
        if self.strategy:
            self.strategy.sort(self.data)
        else:
            raise TypeError


li = list(range(100000))
random.shuffle(li)


context = Context(li, MergeSort())
context.do_strategy()
#print(context.data)

random.shuffle(context.data)

context.set_strategy(QuickSort())
context.do_strategy()

战术方式

一3、模板方法方式

亚洲必赢官网 45

图谋:定义1个操作中的算法的骨子,而将一些手续延迟到子类中。模板方法使得子类能够不退换1个算法的构培育能够重定义该算法的一些特定步骤。
角色:
  抽象类(AbstractClass):定义抽象的原子操作(钩子操作);达成3个模板方法作为算法的骨架。
  具体类(ConcreteClass):完毕原子操作
适用场景:
  一遍性落成贰个算法的不改变的壹对,并将可变的一颦一笑留给子类来贯彻。
  种种子类中的公共行为应该被提收取来并汇总到二个集体父类中以制止代码重复。
  调整子类扩充。模板方法只在一定点调用某操作,这样就只允许在那么些点进展扩展。

优点:
  定义了1多元可接纳的算法和行为
  解决了有的规则语句
  能够提供一样行为的差别落成
缺点:
  客户必须精晓差别的安顿
  计谋与上下文之间的通讯支出
  扩大了对象的多寡

亚洲必赢官网 46亚洲必赢官网 47

from abc import ABCMeta, abstractmethod


class IOHandler(metaclass=ABCMeta):
    @abstractmethod
    def open(self, name):
        pass
    @abstractmethod
    def deal(self, change):
        pass
    @abstractmethod
    def close(self):
        pass
    def process(self, name, change):
        self.open(name)
        self.deal(change)
        self.close()

class FileHandler(IOHandler):
    def open(self, name):
        self.file = open(name,"w")

    def deal(self, change):
        self.file.write(change)

    def close(self):
        self.file.close()


f = FileHandler()
f.process("abc.txt", "Hello World")

模板方法格局

 

厂子方法

定义:“定义制造对象的接口,让子类决定实例化哪叁个类。工厂方法使得一个类的实例化延迟到其子类。”

流程:依照要求,创造差异的厂子(传承自基类),不一样的工厂创设区别的操作类(承袭自基类),使用那么些操作类,调用基类的章程,完结需要。

    FactoryBase* facBase;
    if ([strOperation isEqualToString:@"+"]) {
        facBase = [[AddFactoy alloc] init];
    }else if([strOperation isEqualToString:@"-"]){
        facBase = [[SubFactory alloc] init];
    }else if([strOperation isEqualToString:@"*"]){
        facBase = [[MulFactory alloc] init];
    }else if([strOperation isEqualToString:@"/"]){
        facBase = [[DivFactory alloc] init];
    }    
    Operation* oper;
    oper = [facBase createOperate];
    oper.firstNum = [strFirstNum doubleValue];
    oper.secondNum = [strSecondNum doubleValue];
    self.resultTextField.text = [NSString stringWithFormat:@"%f",[oper getResult]];

虚幻工厂

定义:“定义创制对象的接口,让子类决定实例化哪多少个类。工厂方法使得2个类的实例化延迟到其子类。”

贰个厂子,平日不可能只产1种产品,恐怕须求出现壹种类产品,那时就必要利用抽象工厂

        // id<AbstractFactory> factory = [[HTML5Factory alloc] init];
        id<AbstractFactory> factory = [[OWCFactory alloc] init];

        // 产品1
        id<AbstractLine> line = [factory createLine];

        // 产品2
        id<AbstractPie> pie = [factory createPie];

        [line drawLine];
        [pie drawPie];

参考

iOS常用的设计方式
GitHub上的整治的设计形式大全

网站地图xml地图