(15) - 几个设计模式

---------------------- ASP.Net+Android+IO开发S.Net培训、期待与您交流! ----------------------


设计模式种类较多,这里我只记录下学习过程中的几种设计模式,它们分别为单例,装饰,模板方法,享元,工厂设计模式,其它模式有待学习。

 

1、 单例设计模式


目的:希望对象只创建一个实例,那么需保证一个类在内存中的对象唯一。

 

比如:多个程序读取一个配置文件,那么将配置文件封装成对象,这样会方便文件中的数据操作,为了数据的正确性,又得保证多个程序读到的是同一个配置文件对象,那么这时配置文件对象需在内存中唯一,采用单例模式。

 

如何实现:

(1)私有化构造函数

(2)创建私用且是静态的本类对象。

(3)定义公有且静态的方法,返回本类对象。

 

两种实现方式:饿汉式和懒汉式。两者区别就是本类对象的创建时间,懒汉式将本类对象的初始化放进了返回本类对象的方法中,延迟了本类对象的初始,在不确定是否使用对象时,懒汉式倒是可以节约内存。下面看具体代码理解:

//饿汉式
class Single{
    private Single(){};
    private static final Single instance = new Single();
    public static Single getInstance (){
        return instance;
    }
}

 

//懒汉式
class Single
{
       private Single(){}
       private static Single instance = null;
       public static Single getInstance()
       {
               if(instance==null){
                      //防止多线程下的同步问题
                      synchronized(Single.class)
                      {
                             if(instance == null){
                                    instance = new  Single();
                             }
                      }
               }
               return instance;
       }
}

 

一般实际开发中都是使用饿汉式,懒汉式在多线程下会出现同步问题,上述懒汉式代码加了同步锁,并以双重判断提高效率,不过也是由于这些处理,在效率上还是低于饿汉式。


2、 装饰设计模式

装饰设计模式要做的是动态的给一个对象添加一些额外的职责。相对于派生子类去扩展功能,装饰模式扩展更灵活。

 

若一个父类有子类,子类要增强功能,考虑封装性,我们为子类再增加一个子类用来增强功能的,那么有这么一种情况,父类每增加一个子类,子类又得附带一个子类,结果子类过多膨胀,这时考虑装饰模式。定义一个专门的装饰类,哪个子类要增强功能,就用该装饰类包装。

 

像IO流的输入输出缓冲方式,采用了装饰模式。

 

适用性:

(1)   在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。

(2)   处理那些可以撤销的职责。

(3)   当不能采用生成子类的方法进行扩充时。

看示例,有多个子类,只需一个装饰类就可:


interface  iReader{
    public void read();
}
//子类1
class ReadJpg  implements  iReader{
@Override
public void read(){
        System.out.println("一点点读");
}
}
//子类2,或者有多个
class ReadTxt  implements iReader{
@Override
public void read(){
        System.out.println("一点点读");
}
}
//只要一个装饰类,增加缓冲区功能,先快速读到缓冲区,再一行行从缓冲区读
class  ReadBuffer  implements iReader
{
    private iReader rd;
    public ReadBuffer(iReader rd){
        this.rd = rd;
}
@Override
public void read()
{
        rd.read();
        System.out.println("读到缓冲区,再从缓冲区一行行读");
}
}
public class DecoratorDesign
{
    public static void main(String[] args)
    {
        ReadTxt rt = new ReadTxt();
        ReadBuffer buf = new  ReadBuffer(rt);
        buf.read();
    }
}


3、 模板方法设计模式

即固定可重复使用的部分写成模板,这里加个final写成模板方法,将不确定的部分抽取出来抛给外部(这里是子类)去定义。

比较简单直接看示例代码:

abstract  class Template{
    public abstract void print();
    public final long  printTime(){
        long time = System.currentTimeMillis();
        print();//变化的部分,其余不变
        time = System.currentTimeMillis() -time;
        return time;
    }
}
public class TemplateDesign
{
    public static void main(String[] args)
    {
        //time = 匿名内部类(匿名子类对象).printTime();
               long  time =  new  Template(){
                      //复写print()
                      @Override
                      public void print(){
                             System.out.println("打印1本书....");
                             System.out.println("打印2本书....");
                      }
        }.printTime();
       
        System.out.println(time);
    }
}


4、 享元设计模式

享元模式,即多个使用者共享某一个对象,当然这个对象是具备使用者的共性需求,如有多个使用者,一人有一个对象,但这些对象其实都是些共性方法,为了节约资源,使用者共享一个即可。

来个示例,如要把一串大写字符串转小写,如AAAAAAABBBBC,那么你只需要abc三个小写字母就可以了,每一个大写字母A转换小写a,都是共享了一个a。同理只要26个小写字母,你能转换任意长的大写字母串。

我们将字母当作一个个对象处理,看具体代码:

import java.util.HashMap;
import java.util.Map;
 
//接口,给对象增加行为
interface iFlyweight{
    public abstract void action();
}
//实现
class FlyweightImpl  implements  iFlyweight{
    private String ch;
    public FlyweightImpl(String ch){
        this.ch = ch;
    }
    //字母转换行为
    @Override
    public void action(){
        System.out.println(ch.toLowerCase());
    }
}
//对象工厂,生成对象的
class  FlyweightFactory{
    private static Map map = new HashMap();
    //由ch对象为键值,FlyweightImpl对象为其对应行为
    public iFlyweight  getFlyweight(Stringch){
        //ch对象不存在,则添加一个,存在,则直接获取
        if(map.get(ch) == null){
               map.put(ch, new  FlyweightImpl(ch));
        }
        return (iFlyweight)map.get(ch);
        }
    //看有多少对象
    public int getSize(){
        return map.size();
    }
}
 
//测试类
public class FlyweightDesign
{
    public static void main(String[] args)
    {
        FlyweightFactory factory = new FlyweightFactory();
        //使用对象
        iFlyweight  fly1 = factory.getFlyweight("A");
        fly1.action();
       
        iFlyweight  fly2 = factory.getFlyweight("B");
        fly2.action();
       
        iFlyweight  fly3 = factory.getFlyweight("A");
        fly3.action();
       
        //检测是否在共享一个对象
        System.out.println(fly1 == fly3);
       
        System.out.println(factory.getSize()+"对象");
    }
}

 

其实上述例子,就是一个对象去重复的例子,保证对象的唯一性即可。


5、 工厂设计模式

工厂模式用于创建对象实例的,根据传入的数据,动态的决定需要返回哪一个类的实例。

适用场景:

(1)   当一个类不知道它所创建的对象的类的时候。

(2)   当一个类希望由他的子类来指定它所创建的对象的时候。

下面看以个简单工厂的示例:

//对象接口
interface  iPerson{
}
//实现iPerson接口,即产品对象
class  Student implements  iPerson{
    public Student(){
        System.out.println("学生");
    }
}
 
class  Teacher implements  iPerson{
    public Teacher(){
        System.out.println("老师");
    }
}
 
//简单工厂
class  Factory{
    public iPerson getPerson(String type) {
       
        if(type.equals("student"))
                      return new  Student();
        else if(type.equals("teacher"))
                      return new  Teacher();
       
        return null;
    }
}
 
public class FactoryDesignDemo {
    public static void main(String[] args) {
        Factory fcy = new  Factory();
        iPerson student  =fcy.getPerson("student");
        iPerson teacher  =fcy.getPerson("teacher");
    }
}


---------------------- ASP.Net+Android+IO开发S.Net培训、期待与您交流! ----------------------

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值