楼主: yining

[精华] [专题讨论]设计模式及应用

[复制链接]
论坛徽章:
0
31#
发表于 2003-9-29 15:44 | 只看该作者

有没有讨论其它设计模式的?

有没有兴趣讨论一些其他设计模式之间的比较?

使用道具 举报

回复
论坛徽章:
55
生肖徽章:虎
日期:2006-09-06 21:14:232011新春纪念徽章
日期:2011-01-25 15:41:502011新春纪念徽章
日期:2011-01-25 15:42:152011新春纪念徽章
日期:2011-01-25 15:42:332011新春纪念徽章
日期:2011-01-25 15:42:56管理团队成员
日期:2011-05-07 01:45:082012新春纪念徽章
日期:2012-01-04 11:49:542012新春纪念徽章
日期:2012-02-13 15:11:182012新春纪念徽章
日期:2012-02-13 15:11:182012新春纪念徽章
日期:2012-02-13 15:11:18
32#
 楼主| 发表于 2003-9-29 22:06 | 只看该作者
当然可以,请随便开个题目啊。

使用道具 举报

回复
论坛徽章:
1
授权会员
日期:2005-10-30 17:05:33
33#
发表于 2003-10-4 21:30 | 只看该作者
一个很不错的, 注重模式设计的网站 www.jdon.com

使用道具 举报

回复
论坛徽章:
0
34#
发表于 2003-11-5 16:49 | 只看该作者
不知道是java与模式这本书给我误导还是什么,书上在讲述factory method时候说针对每个具体工厂类对应于每个具体产品类,说这样在产品增加时候只需要增加具体工厂类,客户端不需变化,符合开-闭原则;

我这里有些不同看法,我个人认为factory method模式只是simple factory模式的扩展,simple factory对应于一个具体的产品构建过程,就像我去商店买东西,我要买东西具体是什么东西取决于我买的过程;factory method就象我要买东西,不一定要去商店,可以网上定购,这样就有两个实作,所以定义一个抽象的买的动作,具体如何买由我的具体工厂类实现;其实和在simple factory里面定义重载方法的目的是一样;

另外,在符合开-闭原则上,客户端在选择不同factory method时候也要选择不同的实作,怎么能说客户端代码无需变化哪?

使用道具 举报

回复
论坛徽章:
70
三菱
日期:2014-01-17 10:00:292014年世界杯参赛球队: 智利
日期:2014-06-05 11:54:32马上加薪
日期:2014-04-07 17:03:21马上有钱
日期:2014-02-25 21:39:36马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:11
35#
发表于 2003-12-4 23:17 | 只看该作者
我觉得开闭的说法是限于对已经有的代码而言的。已存在的代码不需要变化。
所以区别在 已有的工厂类需要(简单)或不需要(工厂)修改。楼上的理解怕是有些偏差。

使用道具 举报

回复
论坛徽章:
0
36#
发表于 2003-12-9 20:20 | 只看该作者
Java 与 模式 读书笔记


简单工厂模式:
由一个工厂类根据传入的参量决定创建出哪一种产品类的实例。

涉及角色:
工厂类: 担任这个角色的是工厂方法模式的核心。包含商务逻辑。工厂类常常包含一个静态的方法创建产品对象。通常是一个具体类
抽象产品: 担任这个角色的类是由工厂方法模式创建的类的父类。或者是一个抽象类,或者是一个接口
具体产品角色: 工厂方法模式所创建的任何对象都是这个角色的实例


对于多层次产品结构的实现
只使用一个工厂类,产品的层次不反映到工厂类里来。

简单工厂模式的优缺点以及与设计原则的思考
优点:初步的责任分割。客户端不再直接创建具体产品对象
缺点:工厂类集合了全部的创建逻辑。。当产品类趋向复杂时,工厂类的功能扩展就会很困难
开闭原则:
开闭原则要求系统的设计能够在允许系统在无需要修改的情况下,扩展其功能。
而简单工厂模式只能在消费角色中无需修改就可以接纳新产品。而工厂类必须经过修改才能够增加新的产品类


工厂方法模式
引进了抽象的工厂。将具体产品的创建交给具体工厂实现。可以不修改工厂代码而引入新的产品。

涉及角色:
抽象工厂: 担任这个角色的是工厂方法模式的核心。具体工厂需继承自/实现抽象工厂
具体工厂: 具体工厂中包含商务逻辑。并且受到应用程序的调用来创建产品对象
抽象产品: 产品对象的超类型。
具体产品: 这个角色实现了抽象产品。反映的就是商业上的产品。

对于多层次产品结构的实现
按照产品的层次设计工厂的层次。工厂的层次反映的产品的层次

工厂方法模式的活动序列图
1)        客户端创建ConcreteCreator
2)        客户端调用ConcreateCreator的factory,创建出产品对象


设计原则的考虑
引入新的产品时,原有的客户端代码,抽象工厂,具体工厂代码都不需要改变。需要新增一个具体工厂和一个具体产品就可以了。因而满足开闭原则
依赖倒转的考虑
客户声明工厂和产品时,使用抽象类。因而是满足依赖于抽象编程的概念的


抽象工厂模式
抽象工厂模式的设计是为了解决产品族的问题而出发的。

例如:
室内装修的时候,可以选择两种材料的产品:
木制系列: 木门,木窗
铁制系列: 铁门,铁窗 (监狱用的哈哈)

那么。设想一下单纯使用工厂方法如何处理这个问题。
设计一个抽象工厂类。抽象工厂类有两个方法: 创建门, 创建窗
然后需要一个实际工厂类。实际工厂类来实现这两个方法。。但是,问题在于实际工厂在实现创建门这个方法时,依然不能确定它需要创建的是木门还是铁门。解决的办法就是照搬简单工厂模式,传入个参数类来确定需要创建木门还是铁门。 但这样一来,具体工厂类就不满足开闭原则了。

抽象工厂模式的解决办法是:引入两个具体工厂类,一个用来创建木制系列,一个用来创建铁制系列。
这样,新加入产品系列的时候,可以通过添加新的具体工厂类来解决。
不完善的地方是:如果需要添加一个新的产品,如木桌/铁桌,则所有的工厂类面临着改变。

抽象工厂模式的角色
抽象工厂角色:担任这个角色的是抽象工厂模式的核心。与系统的商业逻辑无关。
具体工厂类角色:这个角色包含商业逻辑,用来创建合适的产品对象
抽象产品角色:
具体产品角色:

考虑使用抽象工厂的场合
1)        一个系统部应当依赖于产品类实例如何被创建,组合和表达的细节。
2)        一个系列的产品有多于一个的产品族,而系统只消费其中一族
3)        同属于同一个产品族的产品是在一起使用的。
4)        系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。

设计原则的考虑
增加新的产品族: 满足开闭原则。只需要增加新的具体工厂类就可以了。
增加新的产品类:不满足开闭原则。所有的工厂类需要改变。

使用道具 举报

回复
论坛徽章:
0
37#
发表于 2003-12-9 23:27 | 只看该作者
Java与模式 读书笔记(2)

单件
单例模式的三个要点,1:类只能有一个实例。2 它必须自行创建这个实例。3。它必须向整个系统提供这个实例

资源管理器常常被设计成单例
单例模式的三种结构

饿汉式:
类被加载时初始化。

[php]
public class EagerSingleton
{
    private static final EagerSingleton m_instance =
        new EagerSingleton();
        
    private EagerSingleton(}()
   
    public static EagerSingleton getInstance()
    {
        return m_instance;
    }
}
[/php]
懒汉式:

[php]
public class LazySingleton
{
    private static LazySingleton
        m_instance = null;
   
    private LazySingleton(){ }
   
    synchronized public static LazySingleton
        getInstance()
    {
        if(m_instance == null)
        {
            m_instance = new LazySingleton();
        }
        return m_instance;
    }
}
[/php]
值得注意的是饿汉式和懒汉式,由于构建函数是私有的,所以都不能继承
登记式单例类 是可以被继承的。

[php]
import java.util.HashMap;
public class RegSingleton
{
    static private HashMap m_registry = new HashMap();
    static
    {
        Regsingleton x = new RegSingleton();
        m_registry.put( x.getClass().getName(), x);
    }
   
    protected RegSingleton(){}
   
    static public RegSingleton getInstance(String name)
    {
        if(name == null)
        {
            name = "com.javapatterns.singleton.demos.RegSingleton";
        }
        if(m_registry.get(name) == null)
        {
            try
            {
                m_registry.put( name, Class.forName(name).newInstance();
            }
            catch(Exception e)
            {
                System.out.println("Error happened.";
            }
        }
        return (RegSingleton)(m_registry.get(name));
    }
   
    public String about()
    {
        return "Hello, I am RegSingleton.";

    }
}
[/php]
下面是子类的一个代码示例

[php]
import java.util.HashMap;
public class RegSingletonChild extends RegSignleton
{
    public RegSingletonChild(){} //***
   
    static public RegSingletonChild getInstance()
    {
        return(RegSingletonChild)
            RegSingleton.getInstance(
            "com.javapatterns.singleton.demos.RegSingletonChild";
    }
   
    public String about()
    {
        return "Hello, I am RegSingletonChild.";
    }
}
[/php]

***由于父类需要创建子类的实例,所以此出的构建函数是public的。这样会带来一个风险,
别人可以直接实例化子类代码。(疑问,为何不能在构建函数中调用getInstance来解决这个问题)

登记式单例模式的另外一个缺陷是必须存在有父类的实例。才能得到子类的实例

错误的单例使用
错误的单例使用大多是试图使用单例去管理资源的生命周期,虽然这是可行的,但是这会使得
对象之间产生不恰当的依赖和耦合关系。
常见的有:企图用单例去管理“全程变量”。管理系统共享的资源如:连接对象等

单例的状态性和分布式系统/多个类加载器系统
单例有可能是是有状态的(如一个序列号生成类),所以在分布式系统/多个类加载器情况下,应该
慎用有状态的单例

例子:管理一个属性文件的单件类:ConfigManager

[php]
package com.javapatterns.singleton.demos;


import java.util.Properties;
import java.io.FileInputStream;
import java.io.File;

/**
* Only once instance of the class may be created during the
* execution of any given program. Instances of this class should
* be aquired through the getInstance() method. Notice that there
* are no public constructors for this class.
*/
public class ConfigManager
{
   /**
        * The private constructor (enforces single instance)
        */
        private ConfigManager()
        {
                m_file = new File(PFILE);
                m_lastModifiedTime = m_file.lastModified();

                if(m_lastModifiedTime == 0)
                {
            System.err.println(PFILE + " file does not exist!";
        }

                m_props = new Properties();

                try
                {
                        m_props.load(new FileInputStream(PFILE));
                }
                catch(Exception e)
                {
                        e.printStackTrace();
                }
        }

        /**
        * Returns the singleton ConfigManager
        *
        * @return The one and only instance of the ConfigManager
        *为什么这里要使用synchronized
        */
        synchronized public static ConfigManager getInstance()
        {
                return m_instance;
        }

        /**
        * Gets a configuration item
        *
        * @param name The name of the item
        * @param defaultVal The default value if name is not found
        * @return The value for the specified name
        */
        final public Object getConfigItem(String name, Object defaultVal)
        {
                long newTime = m_file.lastModified();

                // Check to see if configuration file has been modified
                // since the previous request. If so, then read in the new
                // contents
                if(newTime == 0)
                {
                        // The props file was deleted or does not exist (!!)
                        if(m_lastModifiedTime == 0)
            {
                                System.err.println(PFILE + " file does not exist!";
            }
                        else
            {
                                System.err.println(PFILE + " file was deleted!!";
            }
                        return defaultVal;
                }
                else if(newTime > m_lastModifiedTime)
                {
                        m_props.clear();        // Get rid of the old properties
                        try
                        {
                                m_props.load(new FileInputStream(PFILE));
                        }
                        catch(Exception e)
                        {
                                e.printStackTrace();
                        }
                }
                m_lastModifiedTime = newTime;

                Object val = m_props.getProperty(name);
                if( val == null )
        {
                        return defaultVal;
        }
                else
        {
                        return val;
        }
        }

        /**
        * The fully qualified name of the properties file
        */
        private static final String PFILE = System.getProperty("user.dir" +  "/Singleton.properties";

        /**
        * The File object corresponding to the file that contains the properties
        */
        private File m_file = null;

        /**
        * The last modified time of the properties file
        */
        private long m_lastModifiedTime = 0;

        /**
        * The cached properties
        */
        private Properties m_props = null;

        /**
        * The only instance of this class
        * @label Creates
        */
        private static ConfigManager m_instance = new ConfigManager();

}
[/php]

使用道具 举报

回复
论坛徽章:
0
38#
发表于 2003-12-10 19:34 | 只看该作者
能不能麻烦yining给我讲一下我的疑问?上面两处用粗体标出的。
一个是登记式单例子类的构建函数,一个是最后一个例子中用了同步

使用道具 举报

回复
论坛徽章:
55
生肖徽章:虎
日期:2006-09-06 21:14:232011新春纪念徽章
日期:2011-01-25 15:41:502011新春纪念徽章
日期:2011-01-25 15:42:152011新春纪念徽章
日期:2011-01-25 15:42:332011新春纪念徽章
日期:2011-01-25 15:42:56管理团队成员
日期:2011-05-07 01:45:082012新春纪念徽章
日期:2012-01-04 11:49:542012新春纪念徽章
日期:2012-02-13 15:11:182012新春纪念徽章
日期:2012-02-13 15:11:182012新春纪念徽章
日期:2012-02-13 15:11:18
39#
 楼主| 发表于 2003-12-11 00:04 | 只看该作者
1。疑问,为何不能在构建函数中调用getInstance来解决这个问题

可以,但是造成了互相调用。子类在继承父类的同时,还需要调用父类的方法来创建自己。同时getInstance也在不同的地方负担了两个使命:在client调用中,只负责返回singleton,在子类调用中,只负责创建。这样会造成代码比较难以理解。在debug的时候会成为一个问题。

2。为什么这里要使用synchronized

这是为了多线程的情况下保证只创建一个singleton实例。如果没有这样的保护,有可能会创建多个singleton,同时造成singletong实例之间的脱节。

使用道具 举报

回复
论坛徽章:
70
三菱
日期:2014-01-17 10:00:292014年世界杯参赛球队: 智利
日期:2014-06-05 11:54:32马上加薪
日期:2014-04-07 17:03:21马上有钱
日期:2014-02-25 21:39:36马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:11
40#
发表于 2003-12-11 09:12 | 只看该作者
1。明白。谢谢
2。创建实例是在类加载的时候呀。那个方法是只读的,没有改变任何东西。所以我觉得是笔误

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表