Java–设计模式心得体会

1 语法

 

简述23种软件设计模式

1.1 基础语法

clone

需要操作原对象,但又不想影响原对象.

$K_back = clone $K;

基本数据类型和数组都为真复制,即为真副本,当属性为对象时,为假复制,改变副本仍会影响原对象.解决方案:

//在原对象中添加
function __clone(){
    $this->对象 = clone $this->对象
}

__clone在clone前自动触发,可以执行一些在备份前的属性操作.

&传递引用

方法引用传递,改变源对象

function set_K(& $K){...}

function & get_K(){...}

static延迟静态绑定

应用场景:Dog类和Person类都需要一个返回实例化的方法,Dog类和Person类都继承于Animal抽象类.

abstract class Animal{
    public static function create(){
        //实例化调用类
        return new static();
    }
}

class Person extends Animal{...}

//返回Person实例化类
Person::create();

拦截器

  1. __get($property),访问未定义的属性时调用.
  2. __set($property,$value),给未定义的属性赋值时被调用.
  3. __isset($property),对未定义属性调用isset()方法时调用.
  4. __unset($property),对未定义属性调用unset()方法时调用.
  5. __call($method,$arg_array),调用未定义方法时调用.__call很有用,但要慎用,因为太灵活.应用场景:有一个专门打印Person类信息的Person_Writer类,如果通过Person类调用Person_Writer类.

    //Person委托Person_Writer类处理打印事务.
    class Person {
        private $writer;
        ...
    
        function __call($method_name,$args){
            if(methood_exists($this->wirter,$method_name)){
                return $this->writer->$method_name($this);
            }
        }
    
        //高级__call写法,当委托方法参数不确定时使用.
        function __call($method_name,$args){
            //当然这里这样写法意义不大,但是call一般都是用call_user_func_array调用
            $args = $this ;
            if(methood_exists($this->wirter,$method_name)){
                return call_user_func_array(
                    array($this->writer,$method_name),$args);
                )
            }
        }
    
    }
    

回调函数

应用场景:
3个类,Product类,Product_Sale类,Product_Totalizer类,要实现:当卖出Product总共价格超过指定金额时,输出警告.

//Product
class Product {
    public $name;
    public $price;
}

//Product_Sale
class Product_Sale {
    private $callbacks;

    //记录回调函数
    function register_callback ($callback) {
        if(! is_callback($callback)){
            thow new Exception('callback not callable');
        }
        $this->callbacks[] = $callback;
    }

    //执行回调函数
    function sale ($product){
        print "{$product->name} : 处理中 n";
        foreach($this->callbacks as $callback){
            call_user_func($callback , $product);
        }
    }
}

//Produce_Totalizer
class Produce_Totalizer {
    static function warn_amount ($amt) {
        $count = 0;
        return function ($produce) use ($amt , &count) {
            $count += $produce->price;
            print " count : {count}n"
            if($count>$amt){
                print "quot;超过指定金额{$amt}啦~";
            }
        };
    }
}

//模拟场景
$product_sale = new Produce_Sale();
//指定报警金额为8块
$product_sale = register_callback(Produce_Totalizer::warn_amount(8)); 

//卖商品
$product_sale->sale(new Product("Durex",6));
$product_sale->sale(new Produce("Jissbon",5));

//输出结果
Durex : 处理中
    count :6 

Jissbon : 处理中 
    count: 11

超过指定金额8块啦~

get_class()instanceof

get_class(类)用于判断是否精准等于类名;

instanceof 可以判断是否其本身或继承于某父类.

类中的方法和类中的属性

get_class_methods('类名'):获取类中所有方法.

get_class_vars('类名'):获取类中所有public参数;

反射API

1、策略模式:

一、设计模式分类

2 模式

策略模式就是将能够通用的算法,封装成不同的组件,实现同一个接口,使之可以互换。

总体来说设计模式分为三大类:

2.1 组合

问题:课堂类被演讲类和研讨会类继承着.但是演讲类和研讨类都要实现一次性计费和上N次课计费的方法.和输出计算的方式.

解决方案1:
在课堂类中添加计算一次性付费的方法,上N次课的计费方法和输出计算方式的方法.

解决方案2: 运用组合,将处理计费和输出计算方式单独封装为一个计费策略类.

图片 1

abstract class Cost_Strategy {
    protected $duration;
    abstract function cost ();
    abstract function charge_type();

    public __construct($duration){
        $this->duration = $duration;
    }
}

class Timed_Const_Strategy extends Cost_Stratedy {
    function cost () {
        //上一次课给5块钱- -.
        return $this->duration * 5;
    }

    function charge_type(){
        return "多次课结算";
    }
}

class Fixed_Const_Strategy extends Cost_Stratedy {
    function cost (){
        return 30 ;
    }

    function charge_type(){
        return "一次性课结算";
    }
}

abstract class Leason {

    private $cost_strategy;

    public __construct(Const_Strategy $cost_strategy){
        $this->cost_strategy = $cost_strategy;
    }

    function __call($method_name,$args){
        $args = $cost_strategy ;
        if(methood_exists($this->cost_strategy,$method_name)){
            return call_user_func_array(
                array($this->writer,$method_name),$args);
            )
        }
    }
}

//运用
$leasons[] = new Seminar(new Timed_Const_Strategy(4));
$leasons[] = new Lecture(new Fixed_Const_Strategy(null));

foreach ($leasons as $leason){
    print "leason charge : {$leason->const()}";
    print "charge_type : {$leason->charge_type()}"
}

leason charge 20. charge_type : 多次课结算;
leason charge 30. charge_type : 一次课结算;

组合既委托.同级委托.

继承既父子关系.

例子:SpringMVC的9大组件,都采用策略模式。比如HandlerMethodArgumentResolver,有非常多不同的实现类,这些实现类都可以互相替换来处理不同类型的参数,这就是策略模式。

五种创建型模式:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

3 生成对象

策略模式与模板方法模式的区别:比如一个抽象类有一个抽象方法,每个实现该抽象方法的具体实现都不同,就是模板方法模式,一般在抽象类中会有逻辑处理,只是用到了抽象的模板方法时,交给具体的子类去不同实现。

七种结构型模式:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

3.1 单例模式

确保系统中只有唯一一个用例.例如系统配置文件.

重点

1: 构造方法私有.

2: 类本身包含自己的实例化属性.

图片 2

class Preferences {
    private static $instance;
    private function __construct(){ ... }

    public static function get_instance(){
        if(empty(self::$instance)){
            self::$instance = new Preferences();
        }
        return self::$instance;
    }
    ...
}

//使用
$preferences = Preferences::get_instance();

如果一个模板方法,被子类实现时,实现方式大都相同,比如模板方法为处理字符(10个子类可能只有两种实现,一种是处理为UTF-8,一种是处理成GBK),那么这个模板方法就应该使用策略模式。

十一种行为型模式:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

3.2 工厂模式

通过一个父类,生产处多个不同功能的子类.

特点:产品方(新浪微博)和需求方(显示新浪微博)一一对应.

问题:印象笔记中,来源可能为新浪微博,或者开发者头条,在印象笔记显示的时候,两者的页眉和页尾是不一样的.

图片 3

 

二、设计模式概述

3.3 抽象模式

RLGL!!!.印象笔记不只要显示新浪微博内容!!!还要显示我的新浪账号,还要该微博啊!!卧槽~憋着急,吻我.

工厂模式主要用于生产一一对应的产品方和需求方,而抽象模式要做的是一个需求方(印象笔记_显示新浪微博),要多个工厂(把需求方抽象为多个需求方),例如提供新浪内容的工厂,提供新浪账号的工厂.提供微博内容的评论的工厂等.

图片 4

代码:

abstract class Show_Evernote {
    abstract function get_header_text();
    abstract function get_context();
    abstract function get_footer_text();
    abstract function get_user();
    abstract function get_comment();

}

class 显示新浪微博 extends Show_Evernote{
    function get_header_text(){...};
    function get_context(){new 新浪微博_内容;}
    function get_footer_text(){...};
    function get_user(){new 新浪微博_账号 ;}
    function get_comment(){new 新浪微博_评论;}
}

//使用
印象笔记控件类->内容 = 显示新浪微博->get_context;
印象笔记控件类->账号 = 显示新浪微博->get_context;
...

2、观察者模式:

创建型模式

3.4 平行模式

当使用工厂/抽象模式必须要制定具体的创建者(需求方).

平行模式和抽象模式的模型图一致,但代码实现不一样.

抽象模式中父类均为抽象类,而平行模式中,所以类都为普通类,方便父类的实例化.

在这里列出显示印象笔记类的实现代码

class Show_Evernote{
    private $内容;
    private $账号;
    private $评论;

    function __construct(内容,账号,评论){
        $this->内容 = 内容;
        $this->账号 = 账号;
        $this->评论 = 评论;
    }

    function get_内容(){
        return clone $this->内容);
    }

    function get_账号(){
        return clone $this->账号);
    }

    function get_评论(){
        return clone $this->评论;
    }
}

//使用
$factory = new Show_Evernote( 
    new 新浪微博内容(),
    new 新浪微博账号(),
    new 新浪微博评论()
);

印象笔记控件类->显示印象笔记 = $factory;

其实大家可以发现,原型模式只不过只在最顶层类中包装了一下各组件子类而已,然而这样可以轻松的组合他们,例如实现一个显示新浪微博内容,但要显示开发者头条账号的需求?

观察者模式就是将“观察者”注册给“被观察者”,当被观察者发生改变时,能够及时的通知所有观察者。

1.工厂方法模式

4 使用对象

例子:比如listener或者事件触发等,都是观察者模式

工厂方法模式的创建是因为简单工厂模式有一个问题,在简单工厂模式中类的创建依赖工厂类,如果想要拓展程序,必须对工厂类进行修改,这违背了开闭原则,所以就出现了工厂方法模式,只需要创建一个工厂接口和多个工厂实现类,子类可以自己决定实例化哪一个工厂类,client类针对抽象接口进行编程,如果需要增加新的功能,继承工厂接口,直接增加新的工厂类就可以了,创建过程延迟到子类中进行,不需要修改之前的代码,满足了开闭原则,达到灵活地生产多种对象。

4.1 组合模式

组合模式,可以理解为单一对象管理组合对象(聚合组件),最终组合体下的各个组合部件最好类型一致.不然特殊性越多,需要判断就越多.

假设捶背男,洗脚男,洗发男,用来服务一个人(妹子).

假设妹子的几个部位可用的服务男均为无限个.

图片 5

//创建一个妹子
$妹子 = new 人();

//添加洗脚男、捶背男
$妹子->add_man(new 洗脚男);
$妹子->add_man(new 捶背男);

//循环所有男的给予舒服的方法.
$妹子->计算舒服程度();

这是一个很理想的组合模式,在现实情况,我们使用组合模式,可能不得不创建多种类型的洗脚男,需要添加许多判断条件.

 

2.抽象工厂模式

4.2 装饰模式

装饰模式,首先洗脚男,洗发男,捶背男都是人,但是如果,一个男的又捶背,又洗发,这怎么玩?.add_man两次?这不科学吧,来给这些男的装饰一下吧~

图片 6

abstract class 人{
    ...
    abstract function get_well();
}   

class 男 extends 人 {
    //无论你是神马男,服务你,你就能获得10点舒服度.
    private $well = 10;
    function get_well(){
        return $this->well();
    }
}

abstract class 装饰男类型 extends 人 {
    protected $人;
    function __construct(人 $人){
        $this->人 = $人;
    } 
}

class 捶背装饰 extends 类型男装饰{
    function get_well(){
        return $this->人->get_well()+30;
    }
}

class 洗发装饰 extends 类型男装饰{
    function get_well(){
        return $this->人->get_well()+20;
    }
}

class 洗褪装饰 extends 类型男装饰{
    //老子不喜欢别人碰我的毛裤.
    function get_well(){
        return $this->人->get_well()-20;
    }
}

//创建捶背,能给予的舒服指数 - -嘻嘻.
$人 = new 捶背装饰(new 男);
$人->get_well(); // 10+30 = 40

//来来来,全能选手,捶背、洗发、洗腿一起来
$人 = new 洗脚装饰(new 洗发装饰(new 捶背装饰(new 男()))); //10+30+20-20 = 40,注意顺序,由里到外执行.

装饰模式,既(组合+继承),基类方法一定要尽量少,不然子类可能有它不该有的方法.直接类继承,她只可能是一种形态,而她的多种形态可能一并拥有的时候,应该运用组合.

继承即单一多态,组合既多种多态.

这个例子中,你可以添加女,然后把装饰男类型改为装饰通用类型,但每个get_well()都要多一个判断是男还是女(如果给予的舒服程度不一样).

这只是确保不可能出现在,之外的第三种人,如果基类为动物,给予服务的可能是鸡,鹅,鸭,那么装饰类型应该运用工厂模式,动物形态和装饰形态一一对应.方便拓展.

除了服务类型,服务男的样子也很重要,这就多了一种装饰,现在有装饰男类型相貌男类型,这种情况怎么破,其实类似.

图片 7

//如何获取捶背的帅哥麦?,
$人 =new 男类型(new 捶背(new 帅哥麦(new 男())));

3、装饰者模式:

抽象工厂模式是提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。区别于工厂方法模式的地方,工厂方法模式是创建一个工厂,可以实现多种对象;而抽象工厂模式是提供一个抽象工厂接口,里面定义多种工厂,每个工厂可以生产多种对象。前者的重点在于”怎么生产”,后者的重点在于”生产哪些”;前者是一个抽象产品类,可以派生出多个具体产品类,后者是多个抽象产品类,每个抽象产品类可以派生出多个具体产品类;前者的每个具体工厂类只能创建一个具体产品类的实例,后者的每个具体工厂类可以创建多个具体产品类的实例。

4.3 外观模式

即给外部系统提供清晰接口

例如当Model层写得很混乱,但是里面的方法还能用,那我们的Controller层应该列举一些清晰的访问方法来供View层访问.外观模式,强调的是清晰的访问接口.

装饰者模式就是在不必改变原类文件和使用继承的情况下,动态的扩展对象的的功能。比如你有一个真实对象,有一个包装对象,两个对象都必须实现同一个接口A;但是在进行包装的时候,包装对象需要引用真实对象,然后在真实对象的基础上进行功能扩展,最后返回的都是接口A的对象。但是已经被包装过了,扩展了功能。

3.单例模式

5 执行任务

例子:Java里面的Inputstream与OutputStream就是典型的装饰者模式。

单例模式能保证一个类仅有一个实例,并提供一个访问它的全局访问点,同时在类内部创造单一对象,通过设置权限,使类外部无法再创造对象。单例对象能保证在一个JVM中,该对象只有一个实例存在,这样做的好处就在于如果某些类创建比较频繁,特别是对于一些大型的对象,这是一笔很大的系统开销。在创建的时候,省去了new操作符,降低了系统内存的使用频率,减轻了系统的压力。同时单例模式保证在一个jvm中仅存在一个实例的好处就在于好比一个军队当中只会存在一个最高级别的军官来指挥整个军队,这样才能保证独立控制整个过程,否则如果出现多个,肯定会杂乱无序。

5.1 策略模式

给类添加功能.对象要显式的调用它.

继续刚才的洗脚男和人的故事吧…你丫的爽完了要给钱吧?支付宝?微信?现金?

这个付款方式有多种,实现方法不应该放在类中,而是应该委托给别的类

abstract class 人 {

    protectd $支付方式;

    function set_支付方式(){...}

    function 付款(金额){
        return $支付方式->付款($金额);
    }
}

abstract class 付款{
    abstract function 付款($金额);
}

class 支付宝付款 extends 付款{

    function 付款($金额){
        return 外接支付宝付款流程($金额);
    }
}
...

//使用
$男 =new 男();

///爽爽爽
...

//结账
$支付宝支付账单 = new 支付宝付款($金额);
$人 = new 男();
$人->set_支付方式(new 支付宝付款());
$人->付款();

 

4.建造者模式

5.2 观察者模式

当被观察者发生变化,观察者需要被通知.

当数据发生变化,页面需要被通知.

使用步骤:

  1. 观察者加载到被观察者中.
  2. 被观察者通知观察者.

图片 8

例如登陆类(被观察)状态改变,要出发邮件系统和日志系统(观察者)

interface 被观察者{
    function attach(观察者);
    function detatch(观察者);
    function notify();
}

class Login implements 被观察者{
    private $观察者;

    function __construct(){
        $this->观察者 = array();
    }

    function attach($观察者){
        $this->观察者 = $观察者; 
    }

    function detach($观察者){
        //删除某个观察者的操作;
    }

    function notify(){
        foreach ($this->观察者 as $单个观察者){
            $单个观察者->update($this);
        }
    }       
}

interface 观察者{
    function update(被观察者);
}

abstract class Login_观察者 implements 观察者{
    private $login;
    function __construct (Login $login){
        $this->login = $login;
        $login->attach($this);
    }

    function update(观察者 $观察者){
        if ($观察者 ===$this->login){
            $this->do_update($观察者);
        }
    }
    abstract function do_update(Login $login);
}

class 邮件观察者 extends 登陆观察者 {
    function do_update(Login $login){
        //判断条件 发送邮件
    }
}

class 日志观察者 extends 登陆观察者 {
    function do_update(Login $login){
        //判断条件 记录到日志;
    }
}

//使用
$login = new Login();
new 邮件观察者 ($login);
new 日志观察者 ($login);

PHP有内置的SPL实现上述的观察者模式.

4、工厂方法模式

建造者模式是将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示,就好比是每个饭店或者每家都会做西红柿炒鸡蛋,最后虽然都是西红柿炒鸡蛋的外观,但是由于当中的做饭过程存在差别,所以味道会不同。在程序当中就是将一些不会变的基本组件,通过builder来进行组合,构建复杂对象,实现分离。这样做的好处就在于客户端不必知道产品内部组成的细节;同时具体的建造者类之间是相互独立的,对系统的扩展非常有利,满足开闭原则;由于具体的建造者类是独立的,因此可以对建造过程逐步细化,而不对其他的模块产生任何影响。

5.3 访问者模式

问题:
在一个军队中,有很多军队,军队下面可能包含军队/步兵/弓箭手,这时我们要显示一个军队的战斗力/需要粮食的各级分配?(遍历对象并设置显示方法).怎么办?.解决办法是军队还是保存自己的基本信息,设置一个访问者,访问者包含总战斗力方法和总粮食的方法.

图片 9

访问者

abstract class 军队访问者{
    abstract function 访问(单元);

    function 访问军队($军队){
         $this->访问($军队);
    }
    function 访问弓箭手($弓箭手){
        $this->访问($弓箭手);
    }

    //这里重复定义了大量代码,其实可以用call来替代
    function __call($method_name,$args){
        if(strrpos($method_name, "访问")){
            return call_user_func_array(
                array($this,"访问"),$args
            );
        }
    }
}

class 军队战斗力访问者 extends 军队访问者{
    private $text="";

    function 访问($单元){
        $ret = "";
        $pad = 4*$单元->getDpth(); //设置显示深一级前面多4个空格.
        $ret .= sprintf( "%{$pad}s","");
        $ret .= get_class($单元). ": ";
        $ret .= "战斗力: " .$单元->bombardStrenth()."n";
        $this->text .=$ret;
    }

    function get_text(){
        return $this->text;
    }
}

被访问者

abstract class 单元{
    function 接受($军队访问者){
        $method = "访问_".get_class($this);
        $军队访问者->$method($this);
    }

    private $depth;
    protected function set_depath($depth){
        $this->depth=$depth;
    }

    function get_depth(){
        return $this->depth;
    }
    ...
}

abstract class 综合单元 extends 单元{
    function 接受($军队访问者){
        parent::接受($军队访问者)
        foreach($this->单元集合 as $this_unit){
            $this->unit->接受($军队访问者);
        }
    }
}

class 军队 extends 综合单元{
    function bombardStrenth(){
        $ret =0;
        foreach($this-units() as $unit){
            $ret += $unit->bombardStrenth();
        }
        return $ret
    }
}

class 弓箭手 extends 单元{
    function bombardStrenth(){
        return 4;
    }
}

调用

$main_army = new Army();
$main_army->add_unit(new 步兵());
$main_army->add_unit(new 弓箭手());

$军队战斗力访问者_实例 =new 军队战斗力访问者();
$main_army->接受(均分战斗力访问者);
print $军队战斗力访问者->get_text();

输出

军队: 战斗力: 50
    步兵: 攻击力 :48
    弓箭手: 攻击力: 4

工厂方法模式就是定义一个创建对象的接口,里面有一个创建对象的方法。通过继承或者实现,将对象的创建交给子类。而调用者只用使用接口就可以了,不用关心具体的对象是怎么创建出来的。

5.原型模式

5.4 命令模式

例子为Web页面的login和feed_back,假如都需要使用ajax提交,那么问题来了,将表单封装好提交上去,得到了返回结果.如何根据返回结果跳转不同的页面?.

有些同学就说了,login和feed_back各自写一个方法憋,提交的时候调用各自的方法.

然后再来个logout命令..增加..删除..命令怎么办..

命令模式比较适合命令执行例如登陆,反馈等简单只需要判断是否成功的任务

图片 10

命令:

abstract class Command{
    abstract function execute(Conmmand_Context $context);
}

class Login_Command extends Command{
    function execute(CommandContext $context){
        $managr =Register::getAccessManager();
        $user = $context->get("username");
        $pass = $context->get('pass');
        $user_obj = $manager->login($user,$pass);
        if(is_null($user_obj)){
            $context->setError($manager->getError());
            return false;
        }
        $context->addParam("user",$user_obj);
        return true;
    }
}

部署命令的调用者

class Command_Facotry{
    public function get_command($action){
        $class = UCFirst(strtolower($action))."_Command";
        $cmd = new $class();
        return $cmd;
    }

}

客户端

class Controller{
    private $context;
    function __construct(){
        //Command_Context主要用来存储request和params
        $this->context =new Command_Context();
    }
    function process(){
        $cmd Command_Factory::get_commad($this->context->get('action'));
        if(!$cmd-execute($this->context)){
            //错误处理
        }else{
            //成功 分发视图
        }
    }
}

使用

$controller =new Controller();
$context = $controller->get_context();
$context->add_param('action','login');
$context->add_param('username','404_k');
$context->add_param('pass','123456');
$controller->process();

 

原型模式是用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。其实就是将对象复制了一份并返还给调用者,对象需继承Cloneable并重写clone()方法。原型模式的思想就是将一个对象作为原型,对其进行复制、克隆,产生一个和原对象类似的新对象。分为浅复制和深复制,前者是将一个对象复制后,基本数据类型的变量都会重新创建,而引用类型,指向的还是原对象所指向的;后者是将一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的。

5、抽象工厂模式

结构型模式

抽象工厂模式就是定义一个为创建一组(多个)相关或者相依赖的对象的接口,而调用者无需关心具体的创建对象的实现类。

6.适配器模式

工厂方法模式与抽象工厂模式的区别:当抽象工厂模式定义的接口中只能创建一个对象,那么“抽象工厂模式”就退化成为了“工厂方法模式”。

适配器模式是使得原本由于接口不兼容而不能一起工作的那些类可以一起工作,衔接两个不兼容、独立的接口的功能,使得它们能够一起工作,适配器起到中介的作用。

 

7.装饰模式

6、单例模式

装饰器模式是动态地给一个对象添加一些额外的职责,给一个对象增加一些新的功能,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例。除了动态的增加,也可以动态的撤销,要做到动态的形式,不可以用继承实现,因为继承是静态的。

单例模式这个就不多说了,哈哈,地球人都知道。

8.代理模式

 

代理模式是为其他对象提供一种代理以控制对这个对象的访问,也就是创建类的代理类,间接访问被代理类的过程中,对其功能加以控制。它和装饰器模式的区别在于,装饰器模式为了增强功能,而代理模式是为了加以控制。代理模式就是多一个代理类出来,替原对象进行一些操作,例如买火车票不一定在火车站买,也可以去代售点。再比如打官司需要请律师,因为律师在法律方面有专长,可以替我们进行操作。

7、命令模式

9.外观模式

命令模式就是把请求封装成命令对象,“调用者”就是将“命令对象”传递给“处理对象”。

外观模式是为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。在客户端和复杂系统之间再加一层,提供一个容易使用的外观层。外观模式是为了解决类与类之家的依赖关系的,外观模式就是将他们的关系放在一个Facade类中,降低了类类之间的耦合度,比如搜狐门户网站,就利用了外观模式。

 

10.桥接模式

8、适配器模式

桥接模式是将抽象部分与实现部分分离,使它们都可以独立的变化。桥接模式就是把事物和其具体实现分开,使他们可以各自独立的变化(突然联想到了mvc模式)。将抽象化与实现化解耦,使得二者可以独立变化,就好比现在常说的mvc模式,view和model之间通过control来控制,达到高内聚低耦合来解耦的目的。

适配器模式就是将一个接口转换成为另一个接口。

11.组合模式

 

组合模式是将对象组合成树形结构以表示”部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。创建了一个包含自己对象组的类,并提供修改对象组的方法。在系统的文件和文件夹的问题上就使用了组合模式,文件下不可以有对象,而文件夹下可以有文件对象或者文件夹对象。

9、外观模式

12.享元模式

外观模式提供了一个统一的接口,用来访问系统中的一群接口。外观模式定义了一个高层接口,让使用变得更加容易(不用再去调用一群接口,外观接口已经将一群接口封装好了)。

享元模式是运用共享技术有效地支持大量细粒度的对象。享元模式的主要目的是实现对象的共享,即共享池,当系统中对象多的时候可以减少内存的开销,重用现有的同类对象,若未找到匹配的对象,则创建新对象,这样可以减少对象的创建,降低系统内存,提高效率。

 

行为型模式

10、模板方法模式

13.策略模式

模仿方法模式定义一个操作中算法的框架,而将一些步骤延迟到子类中,使得子类可以不改变算法的结构即可重定义该算法中的某些特定步骤。

策略模式是定义一系列的算法,把它们一个个封装起来,
并且使它们可相互替换,且算法的变化不会影响到使用算法的客户。。是为了统一接口下的一系列算法类(也就是多种策略),用一个类将其封装起来,使这些策略可动态切换。策略模式属于行为型模式,是为了使这些策略可以相互切换,是为了选择不同的行为。

(让子类来实现具体的抽象方法)

14.模版方法模式

 

模板方法模式是定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。该模式就是在一个抽象类中,有一个主方法,再定义1…n个方法,可以是抽象的,也可以是实际的方法,定义一个类,继承该抽象类,重写抽象方法,通过调用抽象类,实现对子类的调用。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤,将一些固定步骤、固定逻辑的方法封装成模板方法。调用模板方法即可完成那些特定的步骤。

11、迭代器模式

15.观察者模式

迭代器模式就是Iterator接口,使得客户可以顺序得访问对象中的各个元素,又不暴露对象内部的细节。

观察者模式是定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。也就是当被观察者状态变化时,通知所有观察者,这种依赖方式具有双向性,在QQ邮箱中的邮件订阅和RSS订阅,当我们浏览一些博客时,经常会看到RSS图标,意思就是,当你订阅了该文章,如果后续有更新,会及时通知你。这种现象即是典型的观察者模式。

 

16.迭代器模式

12、组合模式

迭代器模式是提供一种方法顺序访问一个聚合对象中各个元素,
而又无须暴露该对象的内部表示。在Java当中,将聚合类中遍历各个元素的行为分离出来,封装成迭代器,让迭代器来处理遍历的任务;使简化聚合类,同时又不暴露聚合类的内部,在我们经常使用的JDK中各个类也都是这些基本的东西。

当你将对象的组合(多个对象)组成树结构来展现,那么不管你这个对象是节点(还包含子节点),还是叶子节点(不包含子节点),都可以用一致的方式进行处理。

17.责任链模式

 

责任链模式是避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。有多个对象,每个对象持有对下一个对象的引用,这样就会形成一条链,请求在这条链上传递,直到某一对象决定处理该请求。但是发出者并不清楚到底最终那个对象会处理该请求。在生活中学生进行请假的过程中,会涉及到,学生请假会一级一级往上批,最终处理,具体由谁批准可能不清楚。在程序当中,现在使用的struts拦截器即用到了责任链模式。

13、状态模式

18.命令模式

状态模式是指当前对象把处理自己不同状态的的行为对象,都封装成为自己的属性。当状态发生改变时,调用不同的行为对象,执行不同的操作。(看起来就好像类发生了改变一样)

命令模式是将一个请求封装成一个对象,从而使发出者可以用不同的请求对客户进行参数化。模式当中存在调用者、接收者、命令三个对象,实现请求和执行分开;调用者选择命令发布,命令指定接收者。举个例子,司令员下令让士兵去干件事情,司令员的作用是发出口令,口令经过传递,传到了士兵耳朵里,士兵去执行。司令士兵命令三者相互解耦,任何一方都不用去依赖其他人。其实struts框架也涉及到命令模式的思想。

 

19.备忘录模式

14、代理模式

备忘录模式是在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。创建一个备忘录类,用来存储原始类的信息;同时创建备忘录仓库类,用来存储备忘录类,主要目的是保存一个对象的某个状态,以便在适当的时候恢复对象,也就是做个备份。在系统当中使用的撤销操作,即是使用了备忘录模式,系统可以保存有限次数的文件状态,用户可以进行上几个状态的恢复,也就是用到了备忘录模式。

为另一个对象提供一个替身或占位符以访问这个对象(包装一个对象,并控制对它的访问)

20.状态模式

 

状态模式是允许对象在内部状态发生改变时改变它的行为。对象具有多种状态,且每种状态具有特定的行为。在网站的积分系统中,用户具有不同的积分,也就对应了不同的状态;还有QQ的用户状态有几种状态,在线、隐身、忙碌等,每个状态对应不同的操作,而且你的好友也能看到你的状态。

15、复合模式

21.访问者模式

复合模式结合两个或以上的模式,组成一个解决方案,解决一再发生的一般性问题。(MVC模式就是典型的符合模式;其中Model是观察者模式,发生改变后通知View;View是组合模式,通过各种不同的组件嵌套组成一个完整的View展现用户界面;Controller是策略模式,不同的View可以使用不同的Controller处理不同的业务)

访问者模式主要是将数据结构与数据操作分离。在被访问的类里面加一个对外提供接待访问者的接口,访问者封装了对被访问者结构的一些杂乱操作,解耦结构与算法,同时具有优秀的扩展性。通俗来讲就是一种分离对象数据结构与行为的方法,通过这种分离,可达到为一个被访问者动态添加新的操作而无需做其它的修改的效果。访问者模式的优点是增加操作很容易,因为增加操作意味着增加新的访问者。访问者模式将有关行为集中到一个访问者对象中,其改变不影响系统数据结构。

 

22.中介者模式

16、桥接模式

中介者模式是用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。例如,MVC模式中control就是model和view的中介者。与适配器区别在于,适配器是为了兼容不同的接口,而中介者是为了将显示和操作分离。

 

23.解释器模式

17、建造者(生成器)模式

解释器模式是给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子,基本也就用在这个范围内,适用面较窄,例如:正则表达式的解释等。

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。Spring里面的FactoryBean就是建造者模式

 

18、责任链模式

使多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。(责任链就是一个链表结构,头结点处理完成以后再决定是否要交由下一个节点继续处理,直到没有下一个节点或者其中对象终止责任链)

图片 11

 

19、蝇量模式(享元模式)Flyweight Pattern

享元模式尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象。

应用实例: JAVA 中的
String,如果有则返回,如果没有则创建一个字符串保存在字符串缓存池里面。

 

20、解释器模式

 

21、中介者模式

中介者模式(Mediator
Pattern)是用来降低多个对象和类之间的通信复杂性。这种模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护。中介者模式属于行为型模式。

 

22、备忘录模式

备忘录模式(Memento
Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象。备忘录模式属于行为型模式。

应用实例: 1、后悔药。 2、打游戏时的存档。 3、Windows 里的 ctri +
z。 4、IE 中的后退。 4、数据库的事务管理。

 

23、原型模式

原型模式(Prototype
Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

应用实例: 1、细胞分裂。 2、JAVA 中的 Object clone()
方法。3、Java序列化与反序列化可以实现深度克隆

 

24、访问者模式

访问者模式拥有访问者类,与被访问元素类。元素类通过接受访问者类对象,并且将自身的引用交给访问者,这样访问者就可以使用元素类。

/**
*ComputerPart就是被访问的元素
*ComputerPart通过accept方法接收访问者
*ComputerPartVisitor就是访问者
*/
public interface class ComputerPart {
   public void accept(ComputerPartVisitor computerPartVisitor);
}

/**
*Keyboard就是被访问的元素
*Keyboard实现ComputerPart接口,通过accept方法接收访问者
*Keyboard通过回调访问者computerPartVisitor的visit方法,将自身对象*传给访问者,访问者便可以使用被访问的元素了
*/
public class Keyboard  implements ComputerPart {

   @Override
   public void accept(ComputerPartVisitor computerPartVisitor) {
      computerPartVisitor.visit(this);
   }
}

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注