CodeGym /جاوا بلاگ /Random-SD /مخالف نمونن ڇا آهن؟ اچو ته ڪجھ مثال ڏسون (حصو 1)
John Squirrels
سطح
San Francisco

مخالف نمونن ڇا آهن؟ اچو ته ڪجھ مثال ڏسون (حصو 1)

گروپ ۾ شايع ٿيل
سڀني لاء سٺو ڏينهن! ٻئي ڏينهن مون وٽ نوڪريءَ جو انٽرويو هو، ۽ مون کان مخالف نمونن بابت ڪجهه سوال پڇيا ويا: اهي ڇا آهن، ڪهڙيون قسمون آهن، ۽ ڪهڙا عملي مثال آهن. يقينن، مون سوال جو جواب ڏنو، پر تمام سطحي طور تي، ڇو ته مون اڳ ۾ هن موضوع ۾ تمام گهڻي کوٽائي نه ڪئي هئي. انٽرويو کان پوء، مون انٽرنيٽ کي ڇڪڻ شروع ڪيو ۽ پاڻ کي وڌيڪ ۽ وڌيڪ موضوع ۾ وسايو. مخالف نمونن ڇا آهن؟  اچو ته ڪجھ مثال ڏسون (حصو 1) - 1 اڄ آئون تمام مشهور مخالف نمونن جو مختصر جائزو پيش ڪرڻ ۽ ڪجهه مثالن جو جائزو وٺڻ چاهيندس. مون کي اميد آهي ته هي پڙهڻ توهان کي هن علائقي ۾ گهربل ڄاڻ ڏيندو. اچو ته شروع ڪريون! ان کان اڳ جو اسان بحث ڪريون ته مخالف نموني ڇا آهي، اچو ته ياد ڪريون ته ڊزائن جو نمونو ڇا آهي. هڪ ڊيزائن جو نمونو عام مسئلن يا حالتن لاءِ هڪ ورجائي سگهڻ وارو آرڪيٽيڪچرل حل آهي جيڪو پيدا ٿئي ٿو جڏهن ايپليڪيشن ڊزائين ڪرڻ. پر اڄ اسان انهن جي باري ۾ نه ڳالهائي رهيا آهيون، بلڪه انهن جي مخالف - مخالف نمونن. هڪ مخالف نموني عام مسئلن جي طبقي کي حل ڪرڻ لاء هڪ وسيع پر غير موثر، خطرناڪ، ۽ / يا غير پيداوار وارو طريقو آهي. ٻين لفظن ۾، هي غلطين جو هڪ نمونو آهي (ڪڏهن ڪڏهن هڪ ٽرپ پڻ سڏيو ويندو آهي). ضابطي جي طور تي، مخالف نمونن کي هيٺين قسمن ۾ ورهايو ويو آهي:
  1. آرڪيٽيڪچرل مخالف نمونن - اهي مخالف نمونا پيدا ٿين ٿا جيئن هڪ سسٽم جي جوڙجڪ ٺهيل آهي (عام طور تي هڪ معمار طرفان).
  2. مئنيجمينٽ/ تنظيمي مخالف نمونا - اهي پراجيڪٽ مئنيجمينٽ ۾ مخالف نمونا آهن، عام طور تي مختلف مينيجرز (يا مينيجرز جي گروپن) جي سامهون آهن.
  3. ڊولپمينٽ مخالف نمونن - اهي مخالف نمونا پيدا ٿين ٿا جيئن هڪ سسٽم کي عام پروگرامرز پاران لاڳو ڪيو ويندو آهي.
مخالف نمونن جي مڪمل حد کان وڌيڪ غير معمولي آهي، پر اسان انهن سڀني تي غور نه ڪنداسين اڄ. عام ڊولپرز لاء، اهو تمام گهڻو هوندو. شروعاتن لاءِ، اچو ته غور ڪريون انتظام مخالف نمونو مثال طور.

1. تجزياتي فالج

تجزيي پارليسس کي هڪ کلاسک انتظام مخالف نموني سمجهيو ويندو آهي. ان ۾ منصوبابندي دوران صورتحال جو وڌيڪ تجزيو ڪرڻ شامل آهي، ته جيئن ڪو به فيصلو يا عمل نه ڪيو وڃي، بنيادي طور تي ترقي جي عمل کي مفلوج ڪري ڇڏيو. اهو اڪثر ڪري ٿو جڏهن مقصد تڪميل حاصل ڪرڻ آهي ۽ تجزيو جي دور ۾ بلڪل هر شيء تي غور ڪيو وڃي ٿو. هي مخالف نمونو حلقن ۾ هلڻ (هڪ رن آف دي مل بند لوپ)، نظرثاني ڪرڻ ۽ تفصيلي ماڊل ٺاهڻ، جنهن جي نتيجي ۾ ڪم جي فلو ۾ مداخلت ٿئي ٿي. مثال طور، توهان هڪ سطح تي شين جي اڳڪٿي ڪرڻ جي ڪوشش ڪري رهيا آهيو: پر جيڪڏهن ڪو صارف اوچتو پنهنجي نالي جي چوٿين ۽ پنجين اکرن جي بنياد تي ملازمن جي هڪ فهرست ٺاهڻ چاهي ٿو، جنهن ۾ انهن منصوبن جي فهرست به شامل آهي جن تي هن ڪم جا سڀ کان وڌيڪ ڪلاڪ گذاريا آهن. گذريل چئن سالن کان نئين سال ۽ عورتن جي عالمي ڏينهن جي وچ ۾؟ جوهر ۾، اهو تمام گهڻو تجزيو آهي. هتي تجزياتي فالج سان وڙهڻ لاءِ ڪجھ تجاويز آهن:
  1. توھان کي ضرورت آھي ھڪڙي ڊگھي مدي واري مقصد کي فيصلي ڪرڻ لاءِ بيڪن جي طور تي، جيئن توھان جو ھر فيصلو توھان کي مقصد جي ويجھو وٺي وڃي بجاءِ توھان جي جمود جو سبب بڻجندو.
  2. ننڍين ڳالهين تي توجه نه ڏيو (هڪ غير اهم تفصيل بابت فيصلو ڇو ڪيو ڄڻ ته اهو توهان جي زندگيءَ جو سڀ کان اهم فيصلو هو؟)
  3. فيصلي لاء آخري وقت مقرر ڪريو.
  4. ڪنهن ڪم کي مڪمل طور تي مڪمل ڪرڻ جي ڪوشش نه ڪريو - اهو بهتر آهي ته اهو تمام سٺو.
هتي تمام گهڻي گهري وڃڻ جي ضرورت ناهي، تنهنڪري اسان ٻين انتظامي مخالف نموني تي غور نه ڪنداسين. تنهن ڪري، بغير ڪنهن تعارف جي، اسان اڳتي وڌنداسين ڪجهه آرڪيٽيڪچرل مخالف نمونن تي، ڇاڪاڻ ته هي مضمون گهڻو ڪري مستقبل جي ڊولپرز طرفان پڙهي سگهجي ٿو بلڪه مئنيجر.

2. خدا اعتراض

هڪ خدا آبجیکٹ هڪ مخالف نمونو آهي جيڪو بيان ڪري ٿو هڪ تمام گهڻي ڪنسنٽريشن جي سڀني قسمن جي افعال ۽ وڏي مقدار ۾ مختلف ڊيٽا (هڪ اعتراض جيڪو ايپليڪيشن جي چوڌاري ڦري ٿو). هڪ ننڍڙو مثال وٺو:
public class SomeUserGodObject {
   private static final String FIND_ALL_USERS_EN = "SELECT id, email, phone, first_name_en, access_counter, middle_name_en, last_name_en, created_date FROM users;
   private static final String FIND_BY_ID = "SELECT id, email, phone, first_name_en, access_counter, middle_name_en, last_name_en, created_date FROM users WHERE id = ?";
   private static final String FIND_ALL_CUSTOMERS = "SELECT id, u.email, u.phone, u.first_name_en, u.middle_name_en, u.last_name_en, u.created_date" +
           "  WHERE u.id IN (SELECT up.user_id FROM user_permissions up WHERE up.permission_id = ?)";
   private static final String FIND_BY_EMAIL = "SELECT id, email, phone, first_name_en, access_counter, middle_name_en, last_name_en, created_dateFROM users WHERE email = ?";
   private static final String LIMIT_OFFSET = " LIMIT ? OFFSET ?";
   private static final String ORDER = " ORDER BY ISNULL(last_name_en), last_name_en, ISNULL(first_name_en), first_name_en, ISNULL(last_name_ru), " +
           "last_name_ru, ISNULL(first_name_ru), first_name_ru";
   private static final String CREATE_USER_EN = "INSERT INTO users(id, phone, email, first_name_en, middle_name_en, last_name_en, created_date) " +
           "VALUES (?, ?, ?, ?, ?, ?, ?)";
   private static final String FIND_ID_BY_LANG_CODE = "SELECT id FROM languages WHERE lang_code = ?";
                                  ........
   private final JdbcTemplate jdbcTemplate;
   private Map<String, String> firstName;
   private Map<String, String> middleName;
   private Map<String, String> lastName;
   private List<Long> permission;
                                   ........
   @Override
   public List<User> findAllEnCustomers(Long permissionId) {
       return jdbcTemplate.query( FIND_ALL_CUSTOMERS + ORDER, userRowMapper(), permissionId);
   }
   @Override
   public List<User> findAllEn() {
       return jdbcTemplate.query(FIND_ALL_USERS_EN + ORDER, userRowMapper());
   }
   @Override
   public Optional<List<User>> findAllEnByEmail(String email) {
       var query = FIND_ALL_USERS_EN + FIND_BY_EMAIL + ORDER;
       return Optional.ofNullable(jdbcTemplate.query(query, userRowMapper(), email));
   }
                              .............
   private List<User> findAllWithoutPageEn(Long permissionId, Type type) {
       switch (type) {
           case USERS:
               return findAllEnUsers(permissionId);
           case CUSTOMERS:
               return findAllEnCustomers(permissionId);
           default:
               return findAllEn();
       }
   }
                              ..............private RowMapper<User> userRowMapperEn() {
       return (rs, rowNum) ->
               User.builder()
                       .id(rs.getLong("id"))
                       .email(rs.getString("email"))
                       .accessFailed(rs.getInt("access_counter"))
                       .createdDate(rs.getObject("created_date", LocalDateTime.class))
                       .firstName(rs.getString("first_name_en"))
                       .middleName(rs.getString("middle_name_en"))
                       .lastName(rs.getString("last_name_en"))
                       .phone(rs.getString("phone"))
                       .build();
   }
}
هتي اسان هڪ وڏو طبقو ڏسون ٿا جيڪو سڀ ڪجهه ڪري ٿو. اهو ڊيٽابيس جي سوالن سان گڏوگڏ ڪجهه ڊيٽا تي مشتمل آهي. اسان پڻ ڏسندا آهيون findAllWithoutPageEn facade طريقو، جنهن ۾ ڪاروباري منطق شامل آهي. اهڙي خدائي شئي تمام وڏي ۽ بيوقوف ٿي وڃي ٿي، جنهن کي صحيح طرح برقرار رکيو وڃي. اسان کي ان سان گڏ ڪوڊ جي هر ٽڪڙي ۾ گندا ڪرڻو پوندو. سسٽم جا ڪيترائي حصا ان تي ڀاڙين ٿا ۽ ان سان مضبوطيءَ سان جڙيل آهن. اهڙي ڪوڊ کي برقرار رکڻ ڏکيو ۽ مشڪل ٿي ويندو آهي. اهڙين حالتن ۾، ڪوڊ کي الڳ الڳ طبقن ۾ ورهايو وڃي، جن مان هر هڪ صرف هڪ مقصد هوندو. هن مثال ۾، اسان خدا جي اعتراض کي ڊاء ڪلاس ۾ ورهائي سگهون ٿا:
public class UserDaoImpl {
   private static final String FIND_ALL_USERS_EN = "SELECT id, email, phone, first_name_en, access_counter, middle_name_en, last_name_en, created_date FROM users;
   private static final String FIND_BY_ID = "SELECT id, email, phone, first_name_en, access_counter, middle_name_en, last_name_en, created_date FROM users WHERE id = ?";

                                   ........
   private final JdbcTemplate jdbcTemplate;

                                   ........
   @Override
   public List<User> findAllEnCustomers(Long permissionId) {
       return jdbcTemplate.query(FIND_ALL_CUSTOMERS + ORDER, userRowMapper(), permissionId);
   }
   @Override
   public List<User> findAllEn() {
       return jdbcTemplate.query(FIND_ALL_USERS_EN + ORDER, userRowMapper());
   }

                               ........
}
هڪ ڪلاس جنهن ۾ ڊيٽا ۽ ڊيٽا تائين رسائي جا طريقا شامل آهن:
public class UserInfo {
   private Map<String, String> firstName;..
   public Map<String, String> getFirstName() {
       return firstName;
   }
   public void setFirstName(Map<String, String> firstName) {
       this.firstName = firstName;
   }
                    ....
۽ اهو وڌيڪ مناسب ٿيندو ته طريقي سان ڪاروباري منطق سان هڪ خدمت ڏانهن منتقل ڪرڻ:
private List<User> findAllWithoutPageEn(Long permissionId, Type type) {
   switch (type) {
       case USERS:
           return findAllEnUsers(permissionId);
       case CUSTOMERS:
           return findAllEnCustomers(permissionId);
       default:
           return findAllEn();
   }
}

3. سنگلٽن

سنگلٽن تمام سادو نمونو آهي. اهو يقيني بڻائي ٿو ته هڪ واحد موضوع واري ايپليڪيشن ۾ هڪ طبقي جو هڪ واحد مثال هوندو، ۽ اهو هن اعتراض کي عالمي رسائي پوائنٽ فراهم ڪري ٿو. پر اھو ھڪڙو نمونو آھي يا ھڪڙو مخالف نمونو؟ اچو ته هن نموني جي نقصانن کي ڏسو:
  1. گلوبل اسٽيٽ جڏهن اسان ڪلاس جي مثال تائين پهچون ٿا، اسان کي هن طبقي جي موجوده حالت جي خبر ناهي. اسان کي خبر ناهي ته ڪنهن ان کي تبديل ڪيو يا ڪڏهن. رياست شايد ڪجهه نه ٿي سگهي جيڪا اسان جي اميد آهي. ٻين لفظن ۾، هڪ سنگلٽن سان ڪم ڪرڻ جي درستگي ان جي رسائي جي ترتيب تي منحصر آهي. هن جو مطلب اهو آهي ته سب سسٽم هڪ ٻئي تي منحصر آهن ۽ نتيجي طور، هڪ ڊزائن کي سنجيده وڌيڪ پيچيده ٿي ويندو آهي.

  2. سنگلٽن SOLID اصولن جي ڀڃڪڙي ڪري ٿو - واحد ذميواري اصول: ان جي سڌي فرضن کان علاوه، سنگلٽن ڪلاس مثالن جي تعداد کي به ڪنٽرول ڪري ٿو.

  3. هڪ عام طبقي جو سنگلٽن تي انحصار ڪلاس جي انٽرفيس ۾ نظر نٿو اچي. ڇاڪاڻ ته سنگلٽن مثال عام طور تي طريقي جي دليل جي طور تي منظور نه ڪيو ويندو آهي، پر ان جي بدران سڌو سنئون getInstance() ذريعي حاصل ڪيو ويندو آهي، توهان کي هر طريقي تي عمل ڪرڻ جي ضرورت آهي ته جيئن سنگلٽن تي طبقي جي انحصار کي سڃاڻڻ لاءِ - صرف هڪ طبقي جي عوام کي ڏسندي معاهدو ڪافي نه آهي.

    سنگلٽن جي موجودگي مجموعي طور تي ايپليڪيشن جي قابليت کي گھٽائي ٿي ۽ طبقن جيڪي خاص طور تي سنگلٽن کي استعمال ڪن ٿا. سڀ کان پهريان، توهان سنگلٽن کي ٺٺولي اعتراض سان تبديل نٿا ڪري سگهو. ٻيو، جيڪڏهن هڪ سنگلٽن کي ان جي حالت کي تبديل ڪرڻ لاء هڪ انٽرفيس آهي، ته پوء ٽيسٽ هڪ ٻئي تي منحصر هوندا.

    ٻين لفظن ۾، هڪ سنگلٽن جوڙو وڌائيندو آهي، ۽ مٿي ذڪر ڪيل هر شيءِ وڌايل ملائڻ جي نتيجي کان وڌيڪ ناهي.

    ۽ جيڪڏھن توھان ان جي باري ۾ سوچيو، توھان ھڪڙو سنگل استعمال ڪرڻ کان پاسو ڪري سگھو ٿا. مثال طور، اهو بلڪل ممڪن آهي (۽ حقيقت ۾ ضروري آهي) مختلف قسم جا ڪارخانا استعمال ڪرڻ لاءِ ڪنهن شئي جي مثالن جي تعداد کي ڪنٽرول ڪرڻ لاءِ.

    سڀ کان وڏو خطرو سنگلٽن جي بنياد تي پوري ايپليڪيشن آرڪيٽيڪچر ٺاهڻ جي ڪوشش ۾ آهي. ھن طريقي سان ڪيترائي شاندار متبادل آھن. سڀ کان اهم مثال بهار آهي، يعني ان جي IoC ڪنٽينرز: اهي خدمتن جي تخليق کي ڪنٽرول ڪرڻ جي مسئلي جو هڪ قدرتي حل آهن، ڇاڪاڻ ته اهي اصل ۾ "اسٽيرائڊس تي ڪارخانا" آهن.

    هن وقت هن موضوع تي ڪيترائي اڻ کٽ ۽ اڻ کٽ بحث مباحثا ٿي رهيا آهن. اهو توهان تي آهي فيصلو ڪرڻ لاءِ ته ڇا سنگلٽن هڪ نمونو آهي يا مخالف نمونو.

    اسان ان تي دير نه ڪنداسين. ان جي بدران، اسان اڄ جي آخري ڊيزائن جي نموني ڏانهن وڃو - پولٽرجسٽ.

4. Poltergeist

پولٽريجسٽ هڪ مخالف نمونو آهي جنهن ۾ هڪ بي مقصد طبقو شامل آهي جيڪو استعمال ڪيو ويندو آهي طريقن کي سڏڻ لاءِ ڪنهن ٻئي طبقي جي يا صرف تجريد جي هڪ غير ضروري پرت کي شامل ڪري ٿو . هي مخالف نمونو پاڻ کي مختصر زندگي جي شين وانگر ظاهر ڪري ٿو، رياست کان سواء. اهي شيون اڪثر ڪري استعمال ڪيا ويندا آهن شروعات ڪرڻ لاءِ ٻيون، وڌيڪ مستقل شيون.
public class UserManager {
   private UserService service;
   public UserManager(UserService userService) {
       service = userService;
   }
   User createUser(User user) {
       return service.create(user);
   }
   Long findAllUsers(){
       return service.findAll().size();
   }
   String findEmailById(Long id) {
       return service.findById(id).getEmail();}
   User findUserByEmail(String email) {
       return service.findByEmail(email);
   }
   User deleteUserById(Long id) {
       return service.delete(id);
   }
}
اسان کي اهڙي شيءِ جي ضرورت ڇو آهي جيڪا صرف هڪ وچولي هجي ۽ پنهنجو ڪم ڪنهن ٻئي جي حوالي ڪري؟ اسان ان کي ختم ڪريون ٿا ۽ ٿوري ڪارڪردگي کي منتقل ڪريون ٿا ان کي ڊگھي زندگين شين ڏانهن. اڳيون، اسان انهن نمونن ڏانهن وڃون ٿا جيڪي اسان لاءِ تمام گهڻي دلچسپي وارا آهن (جيئن عام ڊولپرز)، يعني ترقي مخالف نمونن .

5. سخت ڪوڊنگ

تنهنڪري اسان هن خوفناڪ لفظ تي پهچي چڪا آهيون: سخت ڪوڊنگ. هن مخالف نموني جو جوهر اهو آهي ته ڪوڊ مضبوط طور تي هڪ مخصوص هارڊويئر ترتيب ۽ / يا سسٽم ماحول سان ڳنڍيل آهي. هي تمام گهڻو پيچيدگي ڪوڊ کي ٻين ترتيبن ڏانهن پورٽ ڪرڻ. هي مخالف نمونو جادو نمبرن سان ويجھو جڙيل آهي (اهي مخالف نمونا اڪثر جڙيل هوندا آهن). مثال:
public Connection buildConnection() throws Exception {
   Class.forName("com.mysql.cj.jdbc.Driver");
   connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/someDb?characterEncoding=UTF-8&characterSetResults=UTF-8&serverTimezone=UTC", "user01", "12345qwert");
   return connection;
}
درد ٿئي ٿو، نه؟ هتي اسان اسان جي ڪنيڪشن سيٽنگن کي سخت ڪوڊ ڪيو. نتيجي طور، ڪوڊ صحيح طريقي سان ڪم ڪندو صرف MySQL سان. ڊيٽابيس کي تبديل ڪرڻ لاء، اسان کي ڪوڊ ۾ ڊيو ڪرڻ جي ضرورت پوندي ۽ هر شيء کي دستي طور تي تبديل ڪرڻو پوندو. ھڪڙو سٺو حل ھوندو ھڪڙي الڳ فائل ۾ ترتيب ڏيڻ لاء:
spring:
  datasource:
    jdbc-url:jdbc:mysql://localhost:3306/someDb?characterEncoding=UTF-8
    driver-class-name: com.mysql.cj.jdbc.Driver
    username:  user01
    password:  12345qwert
ٻيو اختيار مستقل استعمال ڪرڻ آهي.

6. ٻيڙيءَ جو لنگر

مخالف نمونن جي حوالي سان، هڪ ٻيڙي لنگر جو مطلب آهي سسٽم جي حصن کي رکڻ جو جيڪو ڪجهه بهتر ڪرڻ يا ريفڪٽرنگ ڪرڻ کان پوء استعمال نه ڪيو ويو آهي. انهي سان گڏ، ڪوڊ جا ڪجهه حصا رکي سگهجن ٿا "مستقبل جي استعمال لاء" صرف ان صورت ۾ جيڪڏهن توهان کي اوچتو انهن جي ضرورت هجي. لازمي طور تي، هي توهان جي ڪوڊ کي ڪچري ۾ تبديل ڪري ٿو. مثال:
public User update(Long id, User request) {
   User user = mergeUser(findById(id), request);
   return userDAO.update(user);
}
private User mergeUser(User findUser, User requestUser) {
   return new User(
           findUser.getId(),
           requestUser.getEmail() != null ? requestUser.getEmail() : findUser.getEmail(),
           requestUser.getFirstName() != null ? requestUser.getFirstName() : findUser.getFirstNameRu(),
           requestUser.getMiddleName() != null ? requestUser.getMiddleName() : findUser.getMiddleNameRu(),
           requestUser.getLastName() != null ? requestUser.getLastName() : findUser.getLastNameEn(),
           requestUser.getPhone() != null ? requestUser.getPhone() : findUser.getPhone());
}
اسان وٽ هڪ تازه ڪاري طريقو آهي جيڪو هڪ الڳ طريقو استعمال ڪري ٿو صارف جي ڊيٽا کي ضم ڪرڻ لاءِ ڊيٽابيس مان صارف ڊيٽا کي ضم ڪرڻ لاءِ جيڪو طريقي سان گذري ٿو (جيڪڏهن صارف کي اپڊيٽ جي طريقي سان منظور ڪيو ويو ته هڪ نال فيلڊ آهي، پوءِ پراڻي فيلڊ جي قيمت ڊيٽابيس مان ورتي ويندي آهي) . پوءِ فرض ڪريو ته ڪا نئين گهرج آهي ته رڪارڊ کي پراڻن سان ملائڻ نه گهرجي، پر ان جي بجاءِ، جيتوڻيڪ اتي نال فيلڊز آهن، اهي پراڻين کي اوور رائٽ ڪرڻ لاءِ استعمال ڪيا وڃن ٿا:
public User update(Long id, User request) {
   return userDAO.update(user);
}
هن جو مطلب آهي ته mergeUser هاڻي استعمال نه ڪيو ويو آهي، پر ان کي ختم ڪرڻ لاء افسوس ٿيندو - ڇا ٿيندو جيڪڏهن اهو طريقو (يا هن طريقي جو خيال) ڪنهن ڏينهن ڪم ۾ اچي سگهي ٿو؟ اهڙو ڪوڊ صرف سسٽم کي پيچيده ڪري ٿو ۽ مونجهارو متعارف ڪرايو، بنيادي طور تي ڪابه عملي قدر ناهي. اسان کي اهو نه وسارڻ گهرجي ته "مئل ٽڪرن" سان اهڙو ڪوڊ هڪ ساٿي ڏانهن منتقل ڪرڻ ڏکيو ٿيندو جڏهن توهان ڪنهن ٻئي منصوبي لاءِ نڪرندا. ٻيڙيءَ جي اينڪرز سان ڊيل ڪرڻ جو بھترين طريقو آھي ڪوڊ کي ريفيڪٽر ڪرڻ، يعني ڪوڊ جا حصا حذف ڪريو (دل ٽوڙيندڙ، مان ڄاڻان ٿو). اضافي طور تي، جڏهن ڊولپمينٽ شيڊول تيار ڪيو وڃي، اهو ضروري آهي ته اهڙن لنگر جي حساب سان (سهڻ لاء وقت مختص ڪرڻ).

7. اعتراض cesspool

هن مخالف نموني کي بيان ڪرڻ لاء، پهرين توهان کي اعتراض جي تلاء جي نموني سان واقف ٿيڻ جي ضرورت آهي. هڪ آبجیکٹ پول (ريسورس پول) هڪ تخليقي ڊيزائن جو نمونو آهي ، شروعاتي ۽ استعمال لاءِ تيار ڪيل شين جو هڪ سيٽ. جڏهن هڪ ايپليڪيشن کي ڪنهن شئي جي ضرورت هوندي آهي، اهو هن تلاء مان ورتو وڃي ٿو بلڪه ٻيهر ٺاهيو وڃي. جڏهن ڪا شئي وڌيڪ گهربل ناهي، اهو تباهه ناهي. ان جي بدران، اهو تلاء ڏانهن موٽايو ويو آهي. اهو نمونو عام طور تي ڳري شين لاءِ استعمال ڪيو ويندو آهي جيڪي هر وقت ٺاهڻ لاءِ وقت لڳنديون آهن جڏهن اهي گهربل هونديون آهن، جهڙوڪ ڊيٽابيس سان ڳنڍڻ وقت. اچو ته هڪ ننڍڙو ۽ سادو مثال ڏسو. هتي هڪ ڪلاس آهي جيڪو هن نموني جي نمائندگي ڪري ٿو:
class ReusablePool {
   private static ReusablePool pool;
   private List<Resource> list = new LinkedList<>();
   private ReusablePool() {
       for (int i = 0; i < 3; i++)
           list.add(new Resource());
   }
   public static ReusablePool getInstance() {
       if (pool == null) {
           pool = new ReusablePool();
       }
       return pool;
   }
   public Resource acquireResource() {
       if (list.size() == 0) {
           return new Resource();
       } else {
           Resource r = list.get(0);
           list.remove(r);
           return r;
       }
   }
   public void releaseResource(Resource r) {
       list.add(r);
   }
}
هي ڪلاس مٿي ڏنل سنگلٽن پيٽرن/انٽي-پيٽرن جي صورت ۾ پيش ڪيو ويو آهي ، يعني هن قسم جو فقط هڪ اعتراض ٿي سگهي ٿو. اهو ڪجهه خاص Resourceشيون استعمال ڪري ٿو. ڊفالٽ طور، تعمير ڪندڙ پول کي 4 مثالن سان ڀري ٿو. جڏهن توهان هڪ اعتراض حاصل ڪيو، اهو تلاء مان هٽايو ويندو آهي (جيڪڏهن ڪو به موجود ناهي، هڪ ٺاهي وئي ۽ فوري طور تي واپس ڪيو ويو). ۽ آخر ۾، اسان وٽ ھڪڙو طريقو آھي اعتراض کي واپس رکڻ لاء. وسيلا شيون هن طرح نظر اچن ٿا:
public class Resource {
   private Map<String, String> patterns;
   public Resource() {
       patterns = new HashMap<>();
       patterns.put("proxy", "https://en.wikipedia.org/wiki/Proxy_pattern");
       patterns.put("bridge", "https://en.wikipedia.org/wiki/Bridge_pattern");
       patterns.put("facade", "https://en.wikipedia.org/wiki/Facade_pattern");
       patterns.put("builder", "https://en.wikipedia.org/wiki/Builder_pattern");
   }
   public Map<String, String> getPatterns() {
       return patterns;
   }
   public void setPatterns(Map<String, String> patterns) {
       this.patterns = patterns;
   }
}
هتي اسان وٽ هڪ ننڍڙي شئي آهي جنهن ۾ نقشي تي مشتمل آهي ڊزائن جي نمونن جي نالن سان اهم ۽ لاڳاپيل وڪيپيڊيا لنڪس قدر جي طور تي، ۽ گڏوگڏ نقشي تائين رسائي جا طريقا. اچو ته مکيه تي هڪ نظر رکون:
class SomeMain {
   public static void main(String[] args) {
       ReusablePool pool = ReusablePool.getInstance();

       Resource firstResource = pool.acquireResource();
       Map<String, String> firstPatterns = firstResource.getPatterns();
       // use our map somehow...
       pool.releaseResource(firstResource);

       Resource secondResource = pool.acquireResource();
       Map<String, String> secondPatterns = firstResource.getPatterns();
       // use our map somehow...
       pool.releaseResource(secondResource);

       Resource thirdResource = pool.acquireResource();
       Map<String, String> thirdPatterns = firstResource.getPatterns();
       // use our map somehow...
       pool.releaseResource(thirdResource);
   }
}
هتي هر شيءِ ڪافي واضح آهي: اسان هڪ تلاءُ واري شئي حاصل ڪريون ٿا، پول مان وسيلن سان هڪ اعتراض حاصل ڪريون ٿا، ريسورس اعتراض مان نقشو حاصل ڪريو، ان سان ڪجهه ڪريو، ۽ اهو سڀ ڪجهه ان جي جاءِ تي پول ۾ وڌيڪ ٻيهر استعمال لاءِ رکون ٿا. Voila، هي اعتراض تلاء جي ڊيزائن جو نمونو آهي. پر اسان مخالف نموني بابت ڳالهائي رهيا هئاسين، صحيح؟ اچو ته مکيه طريقي سان هيٺ ڏنل ڪيس تي غور ڪريو:
Resource fourthResource = pool.acquireResource();
   Map<String, String> fourthPatterns = firstResource.getPatterns();
// use our map somehow...
fourthPatterns.clear();
firstPatterns.put("first","blablabla");
firstPatterns.put("second","blablabla");
firstPatterns.put("third","blablabla");
firstPatterns.put("fourth","blablabla");
pool.releaseResource(fourthResource);
هتي، ٻيهر، اسان هڪ وسيلا اعتراض حاصل ڪندا آهيون، اسان ان جي نمونن جو نقشو حاصل ڪندا آهيون، ۽ اسان نقشي سان ڪجهه ڪندا آهيون. پر نقشي کي محفوظ ڪرڻ کان پھريائين شيون جي تلاءَ ۾، ان کي صاف ڪيو ويندو آھي ۽ پوءِ خراب ٿيل ڊيٽا سان ڀريو ويندو آھي، ريسورس شئي کي ٻيهر استعمال لاءِ نا مناسب بڻائيندو آھي. هڪ اعتراض جي تلاء جي مکيه تفصيلن مان هڪ آهي ته جڏهن هڪ اعتراض واپس ڪيو ويندو آهي، ان کي ٻيهر ٻيهر استعمال لاء مناسب حالت ۾ بحال ڪرڻ گهرجي. جيڪڏهن تلاءَ ۾ واپس آيل شيون غلط يا اڻ ٺهڪندڙ حالت ۾ رهنديون آهن، ته پوءِ اسان جي ڊيزائن کي آبجیکٹ سيسپول چئبو آهي. ڇا اهو شيون ذخيرو ڪرڻ جو ڪو احساس آهي جيڪي ٻيهر استعمال لاءِ مناسب نه آهن؟ ھن صورتحال ۾، اسان ٺاھي سگھون ٿا اندروني نقشي کي ناقابل بدلائيندڙ ٺاھيندڙ ۾:
public Resource() {
   patterns = new HashMap<>();
   patterns.put("proxy", "https://en.wikipedia.org/wiki/Proxy_pattern");
   patterns.put("bridge", "https://en.wikipedia.org/wiki/Bridge_pattern");
   patterns.put("facade", "https://en.wikipedia.org/wiki/Facade_pattern");
   patterns.put("builder", "https://en.wikipedia.org/wiki/Builder_pattern");
   patterns = Collections.unmodifiableMap(patterns);
}
ڪوششون ۽ نقشي جي مواد کي تبديل ڪرڻ جي خواهش ختم ٿي ويندي UnsupportedOperationException جي مهرباني جو اهي پيدا ڪندا. مخالف نمونن جا ڦڙا آھن جيڪي ڊولپرز کي اڪثر وقت جي گھٽتائي، لاپرواھي، ناتجربيڪاري، يا پروجيڪٽ مينيجرز جي دٻاءُ جي ڪري ملندا آھن. جلدي ڪرڻ، جيڪو عام آهي، مستقبل ۾ ايپليڪيشن لاءِ وڏيون مشڪلاتون پيدا ڪري سگهي ٿو، تنهنڪري توهان کي انهن غلطين بابت ڄاڻڻ جي ضرورت آهي ۽ انهن کان اڳ ۾ ئي پاسو ڪرڻ گهرجي. هي مضمون جو پهريون حصو ختم ڪري ٿو. جاري رکڻ گهرجي...
تبصرا
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION