黑马程序员----java设计模式之装饰设计模式和享元设计模式

------- android培训java培训、期待与您交流! ----------    

 * 装饰设计模式:当想要对已有的对象进行功能加强时,
     * 可以自定义类,将已有的对象传入,基于已存在的功能,提供功能加强。
     * 那么自定义类称之为装饰类。
     * 
     * 装饰类特点:通常通过构造方法将被装饰的对象传入,并基于装饰对象已有的功能进行加强
     * 例如:IO流中fileReader对象提供了read方法读取数据,
     * 但它有个装饰类bufferedReader 提供了readLine()方法一行一行读取数据,在filereader对象功能上提供更强的读取数据方法,所以称之为装饰设计模式。

public class PersonDemo {

     /**
     * @author Administrator
     */
     public static void main(String[] args) {
          Person p=new Person();
          supperPerson sPerson=newsupperPerson(p);
          sPerson.supperChifan();
                  
     }

}

class Person{
    
     public void chifan(){
         System.out.println("吃饭吃饭");
     }
    
}
//自定义类,对被装饰类的对象功能进行加强
class supperPerson{
    
     private Person p;//定义被装饰对象
     //通过构造方法将被装饰的对象传入
     public supperPerson(Person p){
          this.p=p;
     }
     //对被装饰对象功能进行加强
     public void supperChifan(){
           System.out.println("喝点小酒");
            p.chifan();
            System.out.println("那就开始吃饭吧");
     }
    
}

继承与装饰模式

    继承:是使用已存在的类的定义作为基础建立新的类。新类可以增加数据或新的功能,也可以使用父类的方法,但不能选择性的继承父类。优点:提高了代码的重用行,降低了项目开发周期。

      装饰模式:对已有的对象的功能进行加强。特点:通常通过构造函数将被增强的对象传入,并基于被装饰(增强对象)已有的功能加强。

      myReader--------专门用于读取数据的类

          |---MyTextReader

               |--MyBufferTextReader

         |---MyMediaReader

               |--MyBufferMediaReader

 

 上面这种体系说明:myReader下有MyTextReader,MyMediaReader两个子类。MyTextReader下有MyBufferTextReader子类,提供更高效率读取数据的子类,同理MyMediaReader也是一样。因此我们发现如果myreader下有多个子类的话,那么每个子类下都有提供更高效率读取数据的子类。所以这样显得代码有些臃肿。

     于是我们把所有提高读取数据效率的类全部抽取出来,MuBufferReader。

     classMyBufferReader{

        private  MyTextReader  text;

        private  MyMediaReader  media;

        .............

         MyBufferReader(MyTextReader text){}

         MyBufferReader(MyMediaReader media){}

.............

     }

   

   上面这种我们也发现如果存在多个读取数据的类,那么这里将会有多个构造函数将被增加的对象传入.因此发现这样扩展性极差。

   如何提高扩展性呢?? --------找到参数的共同类型,通过多态的形式,可以提高扩展性。

   class MyBufferReaderextends MyReader{

        private  MyReader  r;

        

         MyBufferReader(MyReader r){}//这就是运用装饰设计模式特征,将被增强的对象通过构造函数传入。

 

     }

因为MyTextReader  MyMediaReader 都属于myReader的子类,所以现在结构体系如下:

  

    myReader--------专门用于读取数据的类

         |---MyTextReader

         |---MyMediaReader

         |---MyBufferReader 

总结:装饰模式比继承更灵活,避免了继承体系的臃肿。而且降低了类与类之间的关系。装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提高了更强的功能,所以装饰类和被装饰类属于一个体系中。

 

 享元设计模式:flyweight

 概念:如果很多很小的对象他们有很多相同的东西,那么就可以把他们变成一个对象。还有一些不同的东西,可以作为方法的属性作外部参数的形式传入。称之为外部状态。相同的属性称之为内部状态。

 

 也就是说:也就是说在一个系统中如果有多个相同的对象,那么只共享一份就可以了,不必每个都去实例化一个对象。比如说(这里引用GOF书中的例子)一个文本系统,每个字母定一个对象,那么大小写字母一共就是52个,那么就要定义52个对象。如果有一个1M的文本,那么字母是何其的多,如果每个字母都定义一个对象那么内存早就爆了。那么如果要是每个字母都共享一个对象,那么就大大节约了资源。

 

比如说,一个咖啡店有几种口味的咖啡(拿铁、摩卡、卡布奇诺等等),如果这家店接到分订单要几十杯咖啡。那么显然咖啡的口味就可以设置成共享的,而不必为每一杯单独生成。代码实现如下:

importjava.util.*;
public abstractclass Order {
// 执行卖出动作
public abstract void sell();
}
public classFlavorOrder extends Order {
public String flavor;
// 获取咖啡口味
public FlavorOrder(String flavor) {
   this.flavor = flavor;
}
@Override
public void sell() {
   // TODO Auto-generated method stub
   System.out.println("卖出一份" + flavor + "的咖啡。");
}
}
public classFlavorFactory {
private Map<String, Order> flavorPool = new HashMap<String,Order>();
// 静态工厂,负责生成订单对象
private static FlavorFactory flavorFactory = new FlavorFactory();
privateFlavorFactory() {
}
public staticFlavorFactory getInstance() {
   return flavorFactory;
}
public OrdergetOrder(String flavor) {
   Order order = null;
   if(flavorPool.containsKey(flavor)) {// 如果此映射包含指定键的映射关系,则返回 true
    order = flavorPool.get(flavor);
   }else {
    order = new FlavorOrder(flavor);
    flavorPool.put(flavor, order);
   }
   return order;
}
public intgetTotalFlavorsMade() {
   return flavorPool.size();
}
}
public classClient {
// 客户下的订单
private static List<Order> orders = new ArrayList<Order>();
// 订单对象生成工厂
private static FlavorFactory flavorFactory;
// 增加订单
private static void takeOrders(String flavor) {
   orders.add(flavorFactory.getOrder(flavor));
}
public staticvoid main(String[] args) {
   // 订单生成工厂
   flavorFactory = FlavorFactory.getInstance();
   //增加订单
   takeOrders("摩卡");
   takeOrders("卡布奇诺");
   takeOrders("香草星冰乐");
   takeOrders("香草星冰乐");
   takeOrders("拿铁");
   takeOrders("卡布奇诺");
   takeOrders("拿铁");
   takeOrders("卡布奇诺");
   takeOrders("摩卡");
   takeOrders("香草星冰乐");
   takeOrders("卡布奇诺");
   takeOrders("摩卡");
   takeOrders("香草星冰乐");
   takeOrders("拿铁");
   takeOrders("拿铁");
   //卖咖啡
   for (Order order : orders) {
    order.sell();
   }
   //打印生成的订单java对象数量
   System.out.println("\n客户一共买了 " + orders.size() + " 杯咖啡! ");
   //打印生成的订单java对象数量
   System.out.println("共生成了 " +flavorFactory.getTotalFlavorsMade()
     + " 个 FlavorOrder java对象! ");
}
}
打印结果:

卖出一份摩卡的咖啡。
卖出一份卡布奇诺的咖啡。
卖出一份香草星冰乐的咖啡。
卖出一份香草星冰乐的咖啡。
卖出一份拿铁的咖啡。
卖出一份卡布奇诺的咖啡。
卖出一份拿铁的咖啡。
卖出一份卡布奇诺的咖啡。
卖出一份摩卡的咖啡。
卖出一份香草星冰乐的咖啡。
卖出一份卡布奇诺的咖啡。
卖出一份摩卡的咖啡。
卖出一份香草星冰乐的咖啡。
卖出一份拿铁的咖啡。
卖出一份拿铁的咖啡。

客户一共买了 15 杯咖啡!
共生成了 4 个 FlavorOrderjava对象!

正如输入结果对比所示,把口味共享极大减少了对象数目,减小了内存消耗。

------- android培训java培训、期待与您交流! ---------- 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值