当前位置: 澳门新濠3559 > 编程 > 正文

  和单例模式不同的是,二十三种设计模式及

时间:2019-11-29 05:49来源:编程
工厂情势(Factory pattern)和单例情势同样,是此外生龙活虎种成立型格局。 【设计方式】 参谋博客   《大话设计格局》Python版代码完结   六十一种设计方式及其python达成 布置规范

  工厂情势(Factory pattern)和单例情势同样,是此外生龙活虎种成立型格局。

【设计方式】

参谋博客    《大话设计格局》Python版代码完结    六十一种设计方式及其python达成

布置规范

IOS设计格局的六大布署规范之开放-关闭原则(OCP,Open-Close Principle卡塔尔(英语:State of Qatar)

观察者(Observer)模式

观看者方式包罗:

  • 通报机制(notification)
  • KVO机制

  和单例方式不一样的是,单例方式会成立和保管三个独立的类别的纯粹对象,工厂格局则是用以创制二种不相同类型的类的多少个对象。

大器晚成、设计格局介绍

设计情势(Design Patterns)

  ——可复用面向对象软件的底蕴

  设计情势(Design pattern)是大器晚成套被反复使用、多数人精通的、经过分类编目标、代码设计经历的下结论。使用设计模式是为了可采替代码、让代码更易于被旁人通晓、保障代码可信赖性。 不容争辩,设计情势于己于旁人于系统都是多赢的,设计情势使代码编写制定真正工程化,设计形式是软件工程的内核,就如大厦的一块块砖块相像。项目中型大巴观的使用设计形式能够圆满的减轻广大难题,每一个情势在当今中都有相应的规律来与之对应,每贰个情势描述了二个在大家周边不断重复发生的难题,以至该难点的主旨应用方案,这也是它能被分布应用的由来。

  Christopher亚历克斯ander:“每三个形式描述了叁个在我们周围不断重复发生的难题,以至该难题的建设方案的基本。那样您就可以一回又贰到处利用该方案而毋庸做重复劳动。”每二个设计情势系统地命名、解释和研讨了面向对象系统中多少个入眼的和再度现身的布置。

  设计情势七个基本要素:格局名称、难点、建设方案、效果

通告机制(notification)

寄托机制是代理“风流倜傥对生龙活虎”的对象时期的通讯,而布告机制是广播“意气风发对多”的靶子时期的通讯;
运用手续

    // 通知名
    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];

工厂形式的得以完毕

  轻便的厂子方式由三有的组成:

  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();
// 程序输出:老师的工作是教书育人

 

二、设计形式分类

  卓越的《设计格局》风度翩翩书归咎出23种设计方式,那23种格局又可归为,创设型、结构型和行为型3大类

2.1.创设型方式

  前边讲过,社会化的分工越来越细,自然在软件设计方面也是这么,由此对象的创始和对象的行使分别也就改成了必然趋向。因为对象的创办会消耗掉系统的超多能源,所以单独对指标的创立举行切磋,进而能够快速地创设对象就是创设型形式要斟酌的标题。这里有6个具体的创立型方式可供切磋,它们各自是:

简短工厂形式(Simple Factory);

厂子方法形式(Factory Method);

空泛工厂格局(Abstract Factory);

创作者方式(Builder);

原型方式(Prototype);

单例形式(Singleton)。

证实:严酷来讲,轻松工厂形式不是GoF计算出来的23种设计情势之风姿浪漫。

  和单例模式不同的是,二十三种设计模式及其python实现。正视于继续的创设型格局:工厂方法形式
依据于于整合的成立性形式:抽象工厂情势、创设者格局

2.2 构造型形式

  在解决了对象的制造难题以后,对象的整合以致对象之间的信任关系就成了开垦人士关切的关键,因为啥规划目的的构造、世袭和凭仗关系会潜濡默化到三回九转程序的维护性、代码的强壮性、耦合性等。对象协会的统筹非常轻便反映出设计人士水平的轻重,这里有7个实际的布局型格局可供研讨,它们各自是:

适配器格局(Adapter);

桥模式(Bridge);

结缘形式(Composite);

装潢方式(Decorator);

外观方式(Facade);

享元情势(Flyweight)

代理情势(Proxy);

2.3 行为型情势

在对象的结构和对象的创造难题都消逝理解后,就剩下对象的行事难点了,纵然目的的行事设计的好,那么对象的表现就可以更清晰,它们中间的合营功用就能够拉长,这里有12个绘身绘色的行为型格局可供研究,它们分别是:

解释器格局(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.当程序编写制定的时候,并无法鲜明在转换对象的时候其方便的靶子类型,唯有到程序运营的时候才会鲜明。

    2.在不分明会有几个管理操作的时候,如针对选拔到的数目,管理的逻辑大概会不一致,可能将来还有恐怕会追加新的操作。 

 

3. 设计方式的六大规格

1、开闭原则(Open Close Principle)

  开闭原则正是说:一个软件实体如类、模块和函数应该对扩张开放,对校订关闭。即软件实体应尽大概在不改良原有代码的动静下进行扩大。在前后相继须求开展扩充的时候,无法去更改原有的代码,完结二个热插拔的功能。所以一句话回顾正是:为了使程序的扩充性好,易于维护和升迁。想要达到如此的功效,大家必要选拔接口和抽象类,后边的实际统筹中我们会提到那点。

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

  里氏替换原则(Liskov Substitution Principle LSP卡塔尔(英语:State of Qatar)面向对象设计的基本原则之大器晚成。 里氏代换原则中说,任何基类能够出现的地点,子类一定可以现身。及具备援用基类(父类)的地点必需能透明地应用其子类的目的。LSP是延续复用的基本,唯有当衍生类能够交替掉基类,软件单位的效应不面前碰着震慑时,基类本领真的被复用,而衍生类也能够在基类的基本功上加码新的一颦一笑。里氏代换原则是对“开-闭”原则的增加补充。达成“开-闭”原则的关键步骤就是抽象化。而基类与子类的接轨关系正是抽象化的切实可行贯彻,所以里氏代换原则是对达成抽象化的具体步骤的正经八百。—— From Baidu 百科

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

  这么些是开闭原则的底子,高层模块不应该借助低层模块,二者都应当依据其抽象;抽象不应有凭仗细节;细节应该依赖抽象。换言之,要本着接口编制程序,实际不是指向性落到实处编制程序。具体内容:是对接口编制程序,正视于肤浅而不依据于具体。

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

  这些标准的情趣是:使用多少个隔绝的接口,比使用单个接口要好。依旧叁个收缩类之间的耦合度的意趣,从那儿咱们看来,其实设计形式就是八个软件的设计看法,从大型软件构造出发,为了进步和敬重方便。总计总结:使用四个特意的接口,而不应用单黄金时代的总接口,即客商端不应有凭借那个它没有要求的接口;裁减注重,裁减耦合。

5、迪米特别准予绳(起码知道原则)(德姆eter Principle)

  为啥叫最少知道原则,正是说:八个实体应当尽量少的与此外实体之间时有发生相互功效,使得系统功效模块相对独立。

6、单风流倜傥职责规范:

  不要存在多于七个形成类改动的来由。通俗的说,即二个类只承当黄金时代项职分。

概念

工厂(比如,OperationFactory)
架空产物(比如,Operation)
切实产物(比如,OperationAdd)

四、写在正规介绍设计情势在此之前

面向对象三大特色:封装,世袭,多态

封装:
  1、把多少和函数包装在类里
  2、类的分界节制了大器晚成部卓殊面包车型大巴探望 ---》 私有总体性

世袭:解决代码复用 重写方法叫做:override 重写,复写

多态:父类能够表示子类

抽象类:
  抽象类不可能被实例化
  抽象类的画饼充饥方法,必需在子类中贯彻

接口:
  风姿浪漫种特有的类,证明了非常多情势,必要继续该接口的类必得完成那些艺术。
  效能:限定继继承口的类的方法的称谓及调用方式;掩盖了类的里边贯彻。
  接口便是风姿罗曼蒂克种浮泛的基类(父类),限定世袭它的类必需兑现接口中定义的有个别方法

澳门新濠3559 1澳门新濠3559 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)

接口应用代码例如

简言之工厂

定义:“特意定义多个类来肩负创制别的类的实例,被创建的实例平日具备协同的父类。

事实上正是由三个工厂类,依照传入的参数,动态的调整作而成立出哪叁个出品类的实例。
角色
1.工厂类剧中人物(比方,OperationFactory):轻易工厂格局的大旨,肩负根据传入的参数来实例化具体的制品实例。

2.浮泛产物剧中人物(举例,Operation):平时是工厂产生具体类的父类(或许是现实性类完结的接口卡塔尔(英语:State of Qatar)。

3.活龙活现成品剧中人物(比方,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、简单工厂情势

澳门新濠3559 3

创制对象放在了工厂类中,并非再爆出在异乡,通过工厂类完毕全数操作。

澳门新濠3559 4澳门新濠3559 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)

轻松易行工厂情势

2、工厂方法情势

 澳门新濠3559 6

现实工厂信赖具体付加物

内容:定义三个用以创立对象的接口(工厂接口),让子类决定实例化哪三个付加物类。
角色:
  抽象工厂剧中人物(Creator)
  具体工厂剧中人物(Concrete Creator)
  抽象付加物角色(Product)
  具体成品剧中人物(Concrete Product)
模式特点:定义三个用来创制对象的接口,让子类决定实例化哪一个类。那使得二个类的实例化延迟到其子类。
  那些情势和轻易工厂有分别,简单工厂格局唯有三个工厂,工厂方法方式相比较简单工厂形式将每种具体成品都对应了三个有声有色工厂。

适用项景:
  须要临蓐种种、大量错落有致对象的时候
  供给减少耦合度的时候
  当系统中的成品种类要求经常扩张的时候
优点:
  每种具体产物都对应一个实际工厂类,不须要改进工厂类代码
  隐蔽了对象创制的达成细节
缺点:
  每扩张叁个现实付加物类,就必须扩充一个相应的生气勃勃工厂类

 

内容:不直接向客户端暴露目标创立的兑现细节,而是经过七个厂子类来承当创建成品类的实例。
角色:
  工厂剧中人物(Creator)
  抽象付加物剧中人物(Product)
  具体产物剧中人物(Concrete Product)
优点:
  隐蔽了对象创立的完结细节,工厂依照法规发出不一致功能的类。
  客商端不要求矫正代码
缺点:
  违反了十足职分标准,将创立逻辑两种到一个工厂类里
  当增添新产物时,要求改良工厂类代码,违反了开闭原则

澳门新濠3559 7澳门新濠3559 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)

工厂方法格局

3、抽象工厂方式

 澳门新濠3559 9

思考:提供三个成立生龙活虎多重有关或相互信赖对象的接口,而没有必要点名它们具体的类。

适用性:

  三个系列要独自于它的付加物的创设、组合和象征时。

  叁个体系要由三个成品俯拾即是中的二个来安排时。

  当您要重申生龙活虎三种相关的产物对象的铺排以便实行合营利用时。

  当你提供二个出品类库,而只想映现它们的接口而不是促成时。

内容:定义二个厂子类接口,让工厂子类来创制大器晚成鳞萃比栉相关或互相正视的对象。
例:分娩后生可畏部手提式有线电话机,必要手提式有线电话机壳、CPU、操作系统三类对象开展组装,在那之中每类对象都有例外的档案的次序。对每种具体育工作厂,分别生育风华正茂部手提式无线电话机所急需的多个对象。
角色:
  抽象工厂角色(Creator)
  具体育工作厂角色(Concrete Creator)
  抽象产物剧中人物(Product)
  具体成品剧中人物(Concrete Product)
  客户端(Client)

比较之下工厂方法格局,抽象工厂格局中的每种具体育工作厂都生产风华正茂套付加物。

适用途景:
  系统要独立于产物的创设与组适那个时候
  强调生机勃勃雨后春笋有关的制品对象的准备以便举办协同使用时
  提供多少个出品类库,想隐蔽付加物的现实贯彻时
优点:
  将客商端与类的有板有眼落到实处相分离
  每种工厂创建了叁个完好的付加物各类,使得易于交流产物多元
  有支持成品的后生可畏致性(即付加物中间的束缚关系)
缺点:
  难以支撑新品类的(抽象)成品

澳门新濠3559 10澳门新濠3559 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()

空洞工厂情势

4、建造者格局

 澳门新濠3559 12

意图:将一个复杂对象的创设与它的象征分离,使得同蓬蓬勃勃的塑造进度能够创建分化的代表。

适用途景:
  当成立复杂对象的算法(Director)应该单独于该目的的组成都部队分(Builder)甚至它们的装配格局时
  当协会进度允许被协会的对象有分裂的象征时(分裂Builder)。
角色:
  抽象建造者(Builder)
  具体建造者(Concrete Builder)
  指挥者(Director)
  产品(Product)

  建造者格局与虚幻工厂形式雷同,也用来创制复杂对象。首要分裂是建造者形式主要一步步布局二个复杂对象,而肤浅工厂方式珍视于多少个星罗棋布的付加物对象

优点:
  隐藏了贰个出品的内部结会谈装配过程
  将组织代码与代表代码分开
  能够对组织进程进展越来越小巧的决定

澳门新濠3559 13澳门新濠3559 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)

建造者情势

5、单例格局

 澳门新濠3559 15

计划:成立三个类,保障三个类只有三个实例,并提供一个做客它的全局访问点。单例约等于是全局变量,内部的不二秘技大概会被改换

角色:
  单例(Singleton)
适用途景
  当类只可以有一个实例并且顾客能够从八个明了的访谈点访谈它时;
  当那些唯生龙活虎实例应该是由此子类化可扩展的,并且客商应该不要修正代码就会动用一个恢弘的实例时。
优点:
  对唯风度翩翩实例的受控访问
  单例也便是全局变量,但谨防了命名空间被污染
与单例形式成效相符的定义:全局变量、静态变量(方法)

澳门新濠3559 16澳门新濠3559 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)

单例形式

澳门新濠3559 18澳门新濠3559 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、适配器格局

 澳门新濠3559 20

思量:将一个类的接口调换到顾客愿意的另二个接口。适配器方式使得本来由于接口不相称而不能够一同职业的这个类能够同步坐班。
角色:
  指标接口(Target)
澳门新濠3559,  待适配的类(Adaptee)
  适配器(Adapter)
三种实现方式:
  类适配器:使用多接二连三
  对象适配器:使用组合

适用途景:
  你想行使多少个业已存在的类,而它的接口不相符您的渴求;
  你想创设一个方可复用的类,该类能够与别的不相干的类或不足预感的类(即那叁个接口恐怕不必然包容的类)合作专门的学问。
  (对象适配器)想行使部分业已存在的子类,但不恐怕对每三个都实行子类化以杰出它们的接口。对象适配器能够适配它的父类接口。

类适配器和目的适配器有两样的权衡。
类适配器准则:
  使用一个现实的Adapter类对Adaptee和Target举办相称。结果是当大家想要匹配贰个类以至有着他的子类时,类Adapter将无法自力更生职业。
  使用Adapter可以重定义Adapter的局地作为,因为Adapter是Adaptee的二个子类。
  仅仅引进贰个指标,并无需额外的指针以直接得到adaptee.
对象适配器法则:
  允许多少个Adapter与三个Adaptee -- 即Adaptee自身以至它的具有子类(若是有子类的话卡塔尔国大器晚成一齐不时常候专门的学问。Adapter也得以贰回给持有的Adaptee增添作用。
  使得重定义 Adaptee 的作为比较困苦。那要求生成Adaptee的子类而且使得 艾达pter 援用那些子类并不是援用艾达ptee本人。

澳门新濠3559 21澳门新濠3559 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)

适配器情势

澳门新濠3559 23澳门新濠3559 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))

适配器

7、组合格局

 澳门新濠3559 25

计划:将对象组合成树形构造以代表“部分-全体”的等级次序构造。组合情势使得客商对单个对象和组合对象的应用具备风姿洒脱致性。
角色:
  抽象组件(Component)
  叶子组件(Leaf)
  复合组件(Composite)
  客户端(Client)

适用处景:
  表示对象的“部分-全部”档次布局(特别是布局是递归的)
  希望客商忽视组合对象与单个对象的差别,客户统风华正茂地应用组合构造中的全部指标
优点:
  定义了含蓄基本指标和烧结对象的类档次布局
  简化客商端代码,即顾客端能够同样地应用组合对象和单个对象
  更易于扩张新类型的机件
缺点:
  很难限定组合中的组件

澳门新濠3559 26澳门新濠3559 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()

结合情势

8、代理格局

澳门新濠3559 28

打算:为此外对象提供黄金时代种代理以决定对那些目的的探问。在急需用相比通用和犬牙相制的目的指针代替轻巧的指针的时候,使用Proxy方式。
角色:
  抽象实体(Subject)
  实体(RealSubject)
  代理(Proxy)
适用项景:
  远程代理:为远程的目的提供代理。一个指标在差别的地点空间提供部分代表。
  虚代理:依照须求成立很大的靶子。
  爱抚代理:调整对本来对象的拜望,用于对象有两样访问权限制期限。爱抚代理用于对象应当有例外的拜望权限的时候。比如,在Choices 操作系统[ CIRM93]中肯姆elProxies为操作系统对象提供了访谈保养。 
  智能教导(斯玛特 Reference )代替了简便易行的指针,它在寻访对象时推行一些附加操作。 它的头名用处满含:对针对实际指标的援引计数,那样当该指标未有引用时,能够自动释放它。
优点:
  远程代理:能够隐蔽对象坐落于远程地址空间的实际
  虚代理:能够拓宽优化,比如依照必要成立对象
  怜惜代理:允许在拜会三个指标时有一点增大的内务管理

  当第叁次援引二个漫长对象时,将它装入内部存款和储蓄器。在探望叁个实际指标前,检查是否业已锁定了它,以确认保证别的对象不能够修改它。

澳门新濠3559 29澳门新濠3559 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())

代办形式

9、义务链格局

 澳门新濠3559 31

筹划:使八个对象都有机遇管理诉求,进而制止诉求的发送者和接受者之间的耦合关系。将那些指标连成一条链,并沿着那条链传递该诉求,直到有三个对象管理它停止。
角色:
  抽象管理者(Handler)
  具体管理者(ConcreteHandler)
  客户端(Client)
适用处景:
  有多个指标足以拍卖二个诉求,哪个指标管理由运维时调整
  在不分明选拔者的情况下,向五个对象中的三个付出二个伸手
  可管理一个伸手的靶子集结应被动态钦命。
优点:
  减弱耦合度:三个对象不须要驾驭是任何哪五个对象管理其央求
缺点:
  恳求不保证被选用:链的末端未有管理或链配置错误
例:
  请假部门承认:leader ---> 部门老董 ---> 总主管
  Javascript事件浮升机制

澳门新濠3559 32澳门新濠3559 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)

权利链方式(请假流程卡塔尔国

澳门新濠3559 34澳门新濠3559 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事件管理

10、迭代器方式

澳门新濠3559 36

筹划:提供风度翩翩种办法顺序访谈三个汇集对象中的种种要素,而又无需暴光该目的的内部表示

适用性:
  访谈二个成团对象的剧情而不须求揭露它的当中表示。
  帮忙对聚焦对象的多样遍历。
  为遍历分歧的集纳布局提供贰个统风流倜傥的接口(即, 帮助多态迭代卡塔尔。

金镶玉裹福禄双全方式:__iter__、__next__

澳门新濠3559 37澳门新濠3559 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)

迭代器格局

11、观看者情势

 澳门新濠3559 39

计划:定义对象间的后生可畏种蓬蓬勃勃对多的依据关系,当三个指标的图景发生转移时, 全数注重于它的目的都收获通告并被自动更新。观望者形式又称“揭橥-订阅”情势
角色:
  抽象主旨(Subject)
  具体焦点(ConcreteSubject)——揭橥者
  抽象观看者(Observer)
  具体观望者(ConcreteObserver)——订阅者
适用项景:
  当多少个架航空模型型有双方面,当中三个方面正视于另贰个上边。将那二者封装在单身对象中以使它们得以分级独立地改造和复用。
  当对叁个对象的改变供给同时改良别的对象,而不晓得具体有个别许对象有待更正。
  当贰个对象必需通报其余对象,而它又无法假定其余对象是哪个人。换言之,你不指望那个指标是风姿洒脱环扣生机勃勃环耦合的。
优点:
  目的和观看者之间的悬空耦合最小
  帮忙广播通讯
缺点:
  八个观看者之间互不知道对方存在,由此三个观望者对宗旨的订正可能变成错误的换代。

澳门新濠3559 40澳门新濠3559 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)

观看者格局

12、攻略格局

澳门新濠3559 42

妄图:定义生龙活虎雨后冬笋的算法,把它们叁个个包装起来,并且使它们可相互替换。本格局使得算法可独自于选用它的顾客而转换。
角色:
  抽象计谋(Strategy)
  具体政策(ConcreteStrategy)
  上下文(Context)
适用途景:
  繁多生死相依的类仅仅是行为有异。“战略”提供了意气风发种用几人展览现中的叁个作为来结构三个类的法子。
  必要选取一个算法的分化变体。举个例子,你也许会定义一些反映不意气风发的上空/时间衡量的算法。当这一个变体落成为贰个算法的类等级次序时,能够行使政策格局。
  算法使用了客商端不必要清楚的数目。可接受政策形式以幸免暴光复杂的、与算法相关的数据构造。
  一个类中的四种行为以三个规范语句的样式存在,可以将这一个表现封装如不一致的国策类中。

澳门新濠3559 43澳门新濠3559 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()

安插形式

13、模板方法情势

澳门新濠3559 45

思虑:定义三个操作中的算法的龙骨,而将风流洒脱部分手续延迟到子类中。模板方法使得子类能够不修正二个算法的布局就能够重定义该算法的一点特定步骤。
角色:
  抽象类(AbstractClass):定义抽象的原子操作(钩子操作);完成四个模板方法作为算法的龙骨。
  具体类(ConcreteClass):完结原子操作
适用途景:
  壹次性实现贰个算法的不改变的局地,并将可变的作为留给子类来得以达成。
  种种子类中的公共行为应该被提抽出来并聚焦到三个公家父类中以避免代码重复。
  调节子类扩充。模板方法只在一定点调用某操作,这样就只允许在这里些点开展扩大。

优点:
  定义了生机勃勃多级可选用的算法和行事
  消除了生龙活虎部分准则语句
  能够提供平等行为的两样实现
缺点:
  客商必须询问分歧的宗旨
  计谋与上下文之间的通信支出
  扩张了对象的数量

澳门新濠3559 46澳门新濠3559 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]];

抽象工厂

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

二个厂子,平日不能够只产大器晚成种付加物,恐怕必要出现风流倜傥种类成品,这个时候就要求运用抽象工厂

        // 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上的重新整建的设计形式大全

编辑:编程 本文来源:  和单例模式不同的是,二十三种设计模式及

关键词: