{"id":7930,"date":"2012-10-12T15:41:34","date_gmt":"2012-10-12T07:41:34","guid":{"rendered":"https:\/\/lifeparty.idv.tw\/blog\/?p=7930"},"modified":"2012-10-12T15:53:04","modified_gmt":"2012-10-12T07:53:04","slug":"%e9%a0%98%e5%9f%9f%e7%89%a9%e4%bb%b6%e7%9a%84%e6%a6%82%e5%bf%b5%e6%80%a7%e8%a1%a8%e5%b1%a4%e8%a8%ad%e8%a8%88","status":"publish","type":"post","link":"https:\/\/lifeparty.idv.tw\/blog\/archives\/7930","title":{"rendered":"\u9818\u57df\u7269\u4ef6\u7684\u6982\u5ff5\u6027\u8868\u5c64\u8a2d\u8a08"},"content":{"rendered":"<p>\u5728 <a href=\"http:\/\/zh.wikipedia.org\/zh-tw\/Java\">Java<\/a> <a href=\"http:\/\/en.wikipedia.org\/wiki\/Object-oriented_analysis_and_design\">\u7269\u4ef6\u5c0e\u5411<\/a>\u7684\u4e16\u754c\u4e2d\uff0c\u958b\u767c\u8005\u5b9a\u7fa9<a href=\"http:\/\/en.wikipedia.org\/wiki\/Domain-driven_design\">\u9818\u57df\u7269\u4ef6<\/a>\u5c0d\u61c9\u771f\u5be6\u4e16\u754c\u7684\u6982\u5ff5\uff0c\u4e26\u4e14\u4f9d\u64da\u5be6\u969b\u7684\u696d\u52d9\u6d41\u7a0b\u4f86\u8a2d\u8a08\u670d\u52d9\u4f86\u64cd\u4f5c\u9818\u57df\u7269\u4ef6\u3002\u9818\u57df\u7269\u4ef6\u4ee3\u8868\u9818\u57df\u6982\u5ff5\u7684\u771f\u5be6\u8cc7\u6599\uff0c\u4f46\u5c0d\u65bc\u8a6e\u91cb\u8cc7\u6599\u7684\u62bd\u8c61\u6982\u5ff5\u537b\u6703\u53d7\u5230\u6642\u7a7a\u74b0\u5883\u7684\u5f71\u97ff\u800c\u8b8a\u5316\u3002\u7576\u9818\u57df\u7269\u4ef6\u4e0d\u80fd\u9762\u5c0d\u73fe\u5be6\u800c\u8abf\u6574\uff0c\u90a3\u9ebc\u7cfb\u7d71\u7684\u8a2d\u8a08\u5c07\u8b8a\u5f97\u6108\u4f86\u6108\u7e41\u8907\uff0c\u4f46\u6539\u8b8a\u9818\u57df\u7269\u4ef6\u9700\u8981\u8b8a\u52d5\u8cc7\u6599\u5eab\u53c8\u5f80\u5f80\u662f\u5de5\u7a0b\u6d69\u5927\u8981\u627f\u64d4\u5de8\u5927\u7684\u98a8\u96aa\uff0c\u5230\u5e95\u6709\u6c92\u6709\u5169\u5168\u5176\u7f8e\u7684\u8fa6\u6cd5\u5462\uff1f\u5728\u6b64\u540c\u4eba\u5206\u4eab\u9818\u57df\u7269\u4ef6\u7684\u6982\u5ff5\u6027\u8868\u5c64\u8a2d\u8a08\uff0c\u5b83\u63d0\u4f9b\u958b\u767c\u8005\u81ea\u884c\u5b9a\u7fa9\u9818\u57df\u7269\u4ef6\u6982\u5ff5\u6027\u8868\u5c64\u754c\u9762\uff0c\u4e26\u900f\u904e\u52d5\u614b\u4ee3\u7406\uff0c\u4ee5\u9818\u57df\u7269\u4ef6\u7684\u8cc7\u6599\u81ea\u52d5\u7522\u751f\u9818\u57df\u7269\u754c\u6982\u5ff5\u6027\u8868\u5c64\u7684\u5be6\u4f5c\u3002<!--more--><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-7938\" title=\"Domain Facade\" src=\"https:\/\/lifeparty.idv.tw\/blog\/wp-content\/uploads\/2012\/10\/domainfacade.png\" alt=\"\" width=\"709\" height=\"506\" srcset=\"https:\/\/lifeparty.idv.tw\/blog\/wp-content\/uploads\/2012\/10\/domainfacade.png 886w, https:\/\/lifeparty.idv.tw\/blog\/wp-content\/uploads\/2012\/10\/domainfacade-300x214.png 300w\" sizes=\"auto, (max-width: 709px) 100vw, 709px\" \/><\/p>\n<p>\u9019\u500b\u8a2d\u8a08\u7531 Domain Facade Factory \u7684\u5be6\u4f5c\u53d6\u5f97\u5c0d\u61c9 Domain Object \u7684 Domain Concept Facade \u7269\u4ef6\uff0c\u5b83\u5be6\u73fe Domain Concept Interface \u7684\u65b9\u6cd5\u3002Domain Concept Facade \u662f\u52d5\u614b\u4ee3\u7406\u7269\u4ef6\uff0c\u5b83\u4f7f\u7528 Facade invocation Handler \u4f86\u63a7\u5236 Domain Concept Interface \u65b9\u6cd5\u7684\u904b\u4f5c\u3002\u5176\u7a0b\u5f0f\u6838\u5fc3\u63a7\u5236\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n<pre lang=\"java\">\r\n@Override\r\npublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {\r\n\tMethod mappingDomainObjectMethod = null;\r\n\r\n\ttry {\r\n\t\tmappingDomainObjectMethod = domainObject.getClass().getMethod(methodName, method.getParameterTypes());\r\n\t\tresult = mappingDomainObjectMethod.invoke(mappingDomainObject, args);\r\n\t} catch (NoSuchMethodException e1) {\r\n\t\tif (memberMappers != null) {\r\n\t\t\tCompositeMemberMapper mapper = memberMappers.get(methodName);\r\n\t\t\tClass<?> returnType = method.getReturnType();\r\n\t\t\ttry {\r\n\t\t\t\tresult = mapper.getMember(mappingDomainObject);\r\n\t\t\t} catch (NoSuchFieldException e2) {\r\n\t\t\t\tresult = null;\r\n\t\t\t}\r\n\t\t\tif (result != null && !returnType.isInstance(result)) {\r\n\t\t\t\tthrow new ClassCastException();\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tthrow new NoSuchMethodException();\r\n\t\t}\r\n\t}\r\n}\r\n<\/pre>\n<p>Facade invocation Handler \u64c1\u6709 Domain Object \u7684\u7269\u4ef6\u5be6\u9ad4\u3001\u4e26\u4e14\u8a2d\u5b9a\u4e86\u8907\u5408\u6210\u54e1\u5c0d\u61c9\u8868\u4f86\u5c0d\u61c9 Domain Object \u8907\u5408\u5c6c\u6027\u7684\u5b58\u53d6\u5c0d\u61c9\u3002\u5982\u679c Domain Concept Interface \u5b9a\u7fa9\u7684\u65b9\u6cd5\u662f Domain Object \u5be6\u969b\u5b58\u5728\u5c6c\u6027\u7684\u5b58\u53d6\u65b9\u6cd5\uff0c\u90a3\u9ebc\u5c31\u6703\u900f\u904e Java \u53cd\u5c04\u6a5f\u5236\u5b58\u53d6\u8a72\u5c6c\u6027\uff0c\u4e0d\u7136\u5c31\u6703\u5f9e\u8907\u5408\u6210\u54e1\u5c0d\u61c9\u8868\u4e2d\u627e\u5230\u7b26\u5408\u7684\u8907\u5408\u6210\u54e1\u7684\u5c0d\u61c9\uff0c\u4ee5\u5c0d\u61c9\u8907\u5408\u5c6c\u6027\u7684\u8cc7\u6599\u5b58\u53d6\u3002\u8907\u5408\u6210\u54e1\u7684\u5c0d\u61c9\u5fc5\u9808\u5be6\u4f5c\u4ee5\u4e0b\u754c\u9762\uff1a<\/p>\n<pre lang=\"java\">public interface CompositeMemberMapper {\r\n\r\n    public Object getMember(Object dataOwner) throws Throwable;\r\n\r\n    public void setMember(Object dataOwner, Object value) throws Throwable;\r\n\r\n}<\/pre>\n<p>Facade invocation Handler \u900f\u904e CompositeMemberMapper \u5b58\u53d6 Domain Facade \u7684\u5c6c\u6027\uff0c\u540c\u4eba\u5be6\u4f5c\u4e86\u4e09\u500b\u57fa\u672c\u7684 CompositeMemberMapper\uff1a<\/p>\n<ol>\n<li>ComplexMemberMapper<\/li>\n<li>SimpleMemberMapper<\/li>\n<li>MappingValuesMemberMapper<\/li>\n<\/ol>\n<p>ComplexMemberMappers \u5c0d\u61c9\u7684\u5c6c\u6027\u662f\u805a\u5408\u591a\u500b\u5c6c\u6027\u7684\u503c\u7269\u4ef6\uff08Value Object\uff09\uff0c\u5b83\u9700\u8981\u6307\u5b9a memberInterface \u4f86\u5b9a\u7fa9\u8a72\u503c\u7269\u4ef6\u7684\u754c\u9762\u3001\u4ee5\u53ca\u6307\u5b9a memberMappers \u5c0d\u61c9\u8a72\u503c\u7269\u4ef6\u7684\u5c6c\u6027\u5c0d\u61c9\u3002\u5f9e\u4e0b\u9762\u9019\u6bb5\u7a0b\u5f0f\u78bc\u7684\u7247\u6bb5\u53ef\u4ee5\u77e5\u9053 ComplexMemberMappers \u4e5f\u662f\u5229\u7528\u52d5\u614b\u4ee3\u7406\u6a5f\u5236\u4f86\u81ea\u52d5\u7522\u751f\u503c\u7269\u4ef6\uff0c\u6b64\u5916\u9084\u52a0\u5165\u4e86 Null Object \u7684\u8655\u7406\u3002\u6240\u8b02 Null Object \u7684\u8655\u7406\u662f\u6307\u7576 memberMappers \u6307\u5b9a\u7684\u5c6c\u6027\u6709\u4efb\u4f55\u4e00\u500b\u627e\u4e0d\u5230\u3001\u6216\u662f\u5224\u65b7 Null Object \u7684 memberPredicate\uff08\u672a\u6307\u5b9a\u5247\u4e0d\u6aa2\u67e5\uff09\u7684\u8a55\u4f30\u503c\u70ba\u771f\u5c31\u6703\u7576\u6210 Null Object\uff0c\u53ef\u4ee5\u5b58\u53d6\u5b83\u7684\u65b9\u6cd5\u4e0d\u6703\u7522\u751f Null Assignment \u7684\u7570\u5e38\uff0c\u4f46\u5176\u5305\u542b\u6709\u5b57\u4e32\u53ca\u539f\u751f\u5c6c\u6027\u7684\u503c\u7686\u6703\u56de\u50b3 null\u3002<\/p>\n<pre lang=\"java\">    private void checkSubMembersExists(Object dataOwner) throws Throwable {\r\n        Iterator fieldIterator = memberMappers.keySet().iterator();\r\n        while (fieldIterator.hasNext()) {\r\n            memberMappers.get(fieldIterator.next()).getMember(dataOwner);\r\n        }\r\n    }\r\n\r\n    private Method findGetter(Class<?> objType, String fieldName) throws Throwable {\r\n        Method result = null;\r\n\r\n        if (fieldName != null) {\r\n            StringBuffer methodName = new StringBuffer(GETTER_PREFIX);\r\n\r\n            if (Character.isLowerCase(fieldName.charAt(FIRST_CHAR_INDEX)) &amp;&amp; Character.isLowerCase(fieldName.charAt(SECOND_CHAR_INDEX))) {\r\n                methodName.append(fieldName.substring(FIRST_CHAR_INDEX, FIRST_CHAR_INDEX).toUpperCase());\r\n                methodName.append(fieldName.substring(SECOND_CHAR_INDEX));\r\n            } else {\r\n                methodName.append(fieldName);\r\n            }\r\n\r\n            result = objType.getMethod(methodName.toString(), NONE_PARAMETER_TYPES);\r\n        }\r\n\r\n        return result;\r\n    }\r\n\r\n    @Override\r\n    public Object getMember(Object dataOwner) throws Throwable {\r\n        Object result = null;\r\n        boolean isNull = false;\r\n\r\n        try {\r\n            checkSubMembersExists(dataOwner);\r\n            if (memberPredicate != null) {\r\n                if (!memberPredicate.evaluate(dataOwner)) {\r\n                    throw new Exception();\r\n                }\r\n            }\r\n        } catch (Exception e) {\r\n            isNull = true;\r\n        }\r\n\r\n        InvocationHandler handler = new CompositeMemberInvocationHandler(dataOwner, memberMappers, isNull);\r\n        result = Proxy.newProxyInstance(memberInterface.getClassLoader(), new Class<!--?-->[] { memberInterface, NullCheckable.class }, handler);\r\n\r\n        return result;\r\n    }\r\n\r\n    @Override\r\n    public void setMember(Object dataOwner, Object value) throws Throwable {\r\n        Iterator fieldIterator = memberMappers.keySet().iterator();\r\n        while (fieldIterator.hasNext()) {\r\n            String fieldName = fieldIterator.next();\r\n            Method fieldGetter = findGetter(value.getClass(), fieldName);\r\n\r\n            CompositeMemberMapper mapper = memberMappers.get(fieldName);\r\n            mapper.setMember(dataOwner, fieldGetter.invoke(value, NONE_ARGS));\r\n        }\r\n    }\r\n<\/pre>\n<p>CompositeMemberMapper \u4f7f\u7528 CompositeMemberInvocationHandler \u751f\u6210\u52d5\u614b\u4ee3\u7406\u7269\u4ef6\uff0c\u5f9e\u4e0b\u5217\u7a0b\u5f0f\u7247\u6bb5\u53ef\u4ee5\u770b\u5230\u52d5\u614b\u4ee3\u7406\u7269\u4ef6\u5982\u4f55\u57f7\u884c\u52d5\u614b\u4ee3\u7406\u7269\u4ef6\u5b58\u53d6\u5c6c\u6027\u7684\u65b9\u6cd5\uff0c\u503c\u5f97\u6ce8\u610f\u7684\u662f\u7576\u56de\u50b3\u503c\u70ba null \u6642\uff0c\u9700\u8981\u5224\u65b7\u5c6c\u6027\u70ba\u539f\u751f\u5305\u8986\u578b\u5225\u7684\u6578\u503c\u8f49\u63db\u3002<\/p>\n<pre lang=\"java\">\r\n\t@Override\r\n\tpublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {\r\n\t\tObject result = null;\r\n\t\tString accessType = null;\r\n\t\tString fieldName = null;\r\n\r\n\t\t\/\/ isNull method\r\n\t\tif (IS_NULL.equals(method.getName())) {\r\n\t\t\tresult = nullObject;\r\n\t\t} else {\r\n\t\t\t\/\/ find accessor & fieldName\r\n\t\t\tPattern p = Pattern.compile(METHOD_NAME_REGEX);\r\n\t\t\tMatcher m = p.matcher(method.getName());\r\n\t\t\tif (m.matches()) {\r\n\t\t\t\taccessType = m.group(FIRST_GROUP_INDEX);\r\n\t\t\t\tfieldName = m.group(SECOND_GROUP_INDEX);\r\n\r\n\t\t\t\tp = Pattern.compile(FIRST_UPPER_CASE_REGEX);\r\n\t\t\t\tm = p.matcher(fieldName);\r\n\r\n\t\t\t\tif (m.matches()) {\r\n\t\t\t\t\tfieldName = m.group(FIRST_GROUP_INDEX).toLowerCase() + m.group(SECOND_GROUP_INDEX);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tCompositeMemberMapper memberMapper = memberMappers.get(fieldName);\r\n\t\t\tif (GETTER.equals(accessType) || BOOLEAN_GETTER.equals(accessType)) {\r\n\t\t\t\tresult = (nullObject ? null : memberMapper.getMember(dataOwner));\r\n\t\t\t} else if (SETTER.equals(accessType)) {\r\n\t\t\t\tif (!nullObject) {\r\n\t\t\t\t\tmemberMapper.setMember(dataOwner, args[FIRST_ARG_INDEX]);\r\n\t\t\t\t} else {\r\n\t\t\t\t\t\/\/ set any member to null object\r\n\t\t\t\t\t\/\/ it will happen nothing\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tthrow new UnsupportedOperationException(method.getDeclaringClass().getName() + DOT + method.getName());\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (result == null) {\r\n\t\t\tClass<?> returnType = method.getReturnType();\r\n\t\t\tif (BOOLEAN_TYPE.equals(returnType.getName())) {\r\n\t\t\t\tresult = Boolean.FALSE.booleanValue();\r\n\t\t\t} else if (INTEGER_TYPE.equals(returnType.getName())) {\r\n\t\t\t\tresult = Integer.MIN_VALUE;\r\n\t\t\t} else if (LONG_TYPE.equals(returnType.getName())) {\r\n\t\t\t\tresult = Long.MIN_VALUE;\r\n\t\t\t} else if (DOUBLE_TYPE.equals(returnType.getName())) {\r\n\t\t\t\tresult = Double.MIN_VALUE;\r\n\t\t\t} else if (FLOAT_TYPE.equals(returnType.getName())) {\r\n\t\t\t\tresult = Float.MIN_VALUE;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn result;\r\n\t}\r\n<\/pre>\n<p>SimpleMemberMapper \u5c0d\u61c9\u7c21\u55ae\u5c6c\u6027\uff0c\u4e5f\u5c31\u662f\u70ba\u539f\u751f\u578b\u5225\u6216\u76f8\u5c0d\u61c9\u7684\u5305\u88dd\u985e\u5225\u3001\u4ee5\u53ca\u5b57\u4e32\u5c6c\u6027\u3002\u4e00\u822c\u800c\u8a00\uff0cSimpleMemberMapper \u901a\u5e38\u662f\u5728 ComplexMemberMapper \u7684 memberMappers \u5b9a\u7fa9\u5176\u7d44\u6210\u5c6c\u6027\uff0c\u9664\u975e Domain Object \u7684\u5c6c\u6027\u540d\u7a31\u548c Domain Facade Interface \u5b9a\u7fa9\u7684\u5b58\u53d6\u5c6c\u6027\u65b9\u6cd5\u4e0d\u540c\uff0c\u5426\u5247 SimpleMemberMapper \u4e0d\u6703\u6709\u4efb\u4f55\u4f5c\u7528\uff0c\u56e0\u70ba\u7576 Domain Object \u7684\u5c6c\u6027\u5b58\u5728\uff0c\u6703\u76f4\u63a5\u5b58\u53d6\u5c6c\u6027\u7684\u8cc7\u6599\u800c\u4e0d\u6703\u900f\u904e SimpleMemberMapper \u5b58\u53d6\u5c6c\u6027\u3002<\/p>\n<pre lang=\"java\">\r\n    @Override\r\n    public Object getMember(Object dataOwner) throws Throwable {\r\n        Object result = null;\r\n        Field field = dataOwner.getClass().getDeclaredField(dataOwnerFieldName);\r\n        field.setAccessible(Constants.ACCESSIBLE);\r\n        result = field.get(dataOwner);\r\n        return result;\r\n    }\r\n\r\n    @Override\r\n    public void setMember(Object dataOwner, Object value) throws Throwable {\r\n        Field field = dataOwner.getClass().getDeclaredField(dataOwnerFieldName);\r\n        field.setAccessible(Constants.ACCESSIBLE);\r\n        field.set(dataOwner, value);\r\n    }\r\n<\/pre>\n<p>MappingValuesMemberMapper \u5247\u662f SimpleMemberMapper \u7684\u7279\u4f8b\uff0c\u5b83\u9700\u8981\u6307\u5b9a\u4e00\u500b mappingValues \u7528\u4f86\u5c0d\u61c9 Domain Object \u7684\u5c6c\u6027\u503c\u6703\u5c0d\u61c9\u6210\u4e0d\u540c\u578b\u614b\u7684\u6b04\u4f4d\u503c\uff0c\u6bd4\u5982\u8aaa\u8981\u5f9e\u5b57\u4e32\u578b\u614b &#8220;Y&#8221; \u8b8a\u6210\u5e03\u6797\u578b\u614b\u7684 true\u3002<\/p>\n<pre lang=\"java\">\r\n    @Override\r\n    public Object getMember(Object dataOwner) throws Throwable {\r\n        Object result = super.getMember(dataOwner);\r\n        return mappingValues.get(result);\r\n    }\r\n\r\n    @Override\r\n    public void setMember(Object dataOwner, Object value) throws Throwable {\r\n        Set<Entry<Object, Object>> entrySet = mappingValues.entrySet();\r\n        Iterator<Entry<Object, Object>> iterator = entrySet.iterator();\r\n\r\n        Object data = null;\r\n        while (iterator.hasNext()) {\r\n            Entry<Object, Object> entry = iterator.next();\r\n            if (entry.getValue().equals(value)) {\r\n                data = entry.getKey();\r\n            }\r\n        }\r\n\r\n        if (data != null) {\r\n            super.setMember(dataOwner, data);\r\n        } else {\r\n            throw new UnsupportedOperationException();\r\n        }\r\n    }\r\n<\/pre>\n<p>\u4ee5\u4e0a\u662f\u9818\u57df\u7269\u4ef6\u7684\u6982\u5ff5\u6027\u8868\u5c64\u8a2d\u8a08\u7684\u5927\u81f4\u60c5\u5f62\uff0c\u9019\u500b\u8a2d\u8a08\u5176\u5be6\u53ea\u662f\u518d\u900f\u904e\u4e00\u5c64\u8f49\u63db\u8b93\u9818\u57df\u7269\u4ef6\u66f4\u70ba\u62bd\u8c61\u5316\uff0c\u7576\u7136\u61c9\u8a72\u6709\u4eba\u6703\u89ba\u5f97\u6709\u7591\u554f\u3002\u5982\u679c\u7528 <a href=\"http:\/\/en.wikipedia.org\/wiki\/Hibernate_(Java)\">Hibernate<\/a> \u4f86\u8655\u7406\u9818\u57df\u7269\u4ef6\u7684\u6301\u4e45\u5316\uff0c\u4f3c\u4e4e\u5c31\u4e0d\u7528\u5927\u8cbb\u5468\u7ae0\u5730\u518d\u7d93\u904e\u4e00\u5c64\u8f49\u63db\uff0c\u56e0\u70ba Hibernate \u7684\u8a2d\u5b9a\u672c\u4f86\u5c31\u5f88\u6709\u5f48\u6027\u4e86\u5440\uff01\u9019\u540c\u4eba\u7576\u7136\u77e5\u9053\uff0c\u4f46\u6709\u9019\u500b\u7591\u554f\u7684\u4eba\u6709\u6240\u4e0d\u77e5\uff0c\u6211\u9019\u500b\u8a2d\u8a08\u5c31\u662f\u7528\u5728\u4f7f\u7528 Hibernate \u6846\u67b6\u7684\u67b6\u69cb\u4e0b\u3002\u53ea\u662f\u5049\u5927\u7684 DB Service \u8a2d\u8a08\u4e0d\u628a Hibernate \u5efa\u69cb\u64cd\u4f5c\u7269\u4ef6\u7684\u57fa\u790e\u4e0a\uff0c\u800c\u662f\u4ee5\u64cd\u4f5c\u8cc7\u6599\u8868\u7684\u65b9\u5f0f\u4f86\u4f7f\u7528 Hibernate\uff0c\u5b83\u628a Hibernate \u7684 Component \u7684\u529f\u80fd\u81ea\u52d5\u6392\u9664\u4e86\u3002\u65e2\u7136\u6709\u4eba\u628a\u6211\u5011\u7684 Composite Value Objects \u5077\u8d70\u4e86\uff0c\u90a3\u6211\u53ea\u597d\u5229\u7528\u9019\u500b\u8a2d\u8a08\u8a66\u8457\u628a\u5b83\u5011\u8981\u56de\u4f86\u5440\uff01 <\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u9818\u57df\u7269\u4ef6\u4ee3\u8868\u9818\u57df\u6982\u5ff5\u7684\u771f\u5be6\u8cc7\u6599\uff0c\u4f46\u5c0d\u65bc\u8a6e\u91cb\u8cc7\u6599\u7684\u62bd\u8c61\u6982\u5ff5\u537b\u6703\u53d7\u5230\u6642\u7a7a\u74b0\u5883\u7684\u5f71\u97ff\u800c\u8b8a\u5316\u3002\u7576\u9818\u57df\u7269\u4ef6\u4e0d\u80fd\u9762\u5c0d\u73fe\u5be6\u800c\u8abf\u6574\uff0c\u90a3\u9ebc\u7cfb\u7d71\u7684\u8a2d\u8a08\u5c07\u8b8a\u5f97\u6108\u4f86\u6108\u7e41\u8907\uff0c\u4f46\u6539\u8b8a\u9818\u57df\u7269\u4ef6\u9700\u8981\u8b8a\u52d5\u8cc7\u6599\u5eab\u53c8\u5f80\u5f80\u662f\u5de5\u7a0b\u6d69\u5927\u8981\u627f\u64d4\u5de8\u5927\u7684\u98a8\u96aa\uff0c\u5230\u5e95\u6709\u6c92\u6709\u5169\u5168\u5176\u7f8e\u7684\u8fa6\u6cd5\u5462\uff1f\u5728\u6b64\u540c\u4eba\u5206\u4eab\u9818\u57df\u7269\u4ef6\u7684\u6982\u5ff5\u6027\u8868\u5c64\u8a2d\u8a08\uff0c\u5b83\u63d0\u4f9b\u958b\u767c\u8005\u81ea\u884c\u5b9a\u7fa9\u9818\u57df\u7269\u4ef6\u6982\u5ff5\u6027\u8868\u5c64\u754c\u9762\uff0c\u4e26\u900f\u904e\u52d5\u614b\u4ee3\u7406\uff0c\u4ee5\u9818\u57df\u7269\u4ef6\u7684\u8cc7\u6599\u81ea\u52d5\u7522\u751f\u9818\u57df\u7269\u754c\u6982\u5ff5\u6027\u8868\u5c64\u7684\u5be6\u4f5c\u3002 <a href=\"https:\/\/lifeparty.idv.tw\/blog\/archives\/7930\">\u95b1\u8b80\u5168\u6587 <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[29,24,37,43,19],"tags":[],"class_list":["post-7930","post","type-post","status-publish","format-standard","hentry","category-29","category-24","category-37","category-43","category-19"],"_links":{"self":[{"href":"https:\/\/lifeparty.idv.tw\/blog\/wp-json\/wp\/v2\/posts\/7930","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/lifeparty.idv.tw\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/lifeparty.idv.tw\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/lifeparty.idv.tw\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/lifeparty.idv.tw\/blog\/wp-json\/wp\/v2\/comments?post=7930"}],"version-history":[{"count":34,"href":"https:\/\/lifeparty.idv.tw\/blog\/wp-json\/wp\/v2\/posts\/7930\/revisions"}],"predecessor-version":[{"id":7965,"href":"https:\/\/lifeparty.idv.tw\/blog\/wp-json\/wp\/v2\/posts\/7930\/revisions\/7965"}],"wp:attachment":[{"href":"https:\/\/lifeparty.idv.tw\/blog\/wp-json\/wp\/v2\/media?parent=7930"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/lifeparty.idv.tw\/blog\/wp-json\/wp\/v2\/categories?post=7930"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/lifeparty.idv.tw\/blog\/wp-json\/wp\/v2\/tags?post=7930"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}